diff --git a/public/images/pokemon/exp/back/shiny/778.png b/public/images/pokemon/exp/back/shiny/778.png index 16ed247e24a..2b1c9ecf3c9 100644 Binary files a/public/images/pokemon/exp/back/shiny/778.png and b/public/images/pokemon/exp/back/shiny/778.png differ diff --git a/public/images/pokemon/exp/shiny/778.png b/public/images/pokemon/exp/shiny/778.png index e29b2b2fc20..13fecc069c6 100644 Binary files a/public/images/pokemon/exp/shiny/778.png and b/public/images/pokemon/exp/shiny/778.png differ diff --git a/src/@types/i18next.d.ts b/src/@types/i18next.d.ts new file mode 100644 index 00000000000..0c76c169b51 --- /dev/null +++ b/src/@types/i18next.d.ts @@ -0,0 +1,54 @@ +import { AbilityTranslationEntries, SimpleTranslationEntries, AchievementTranslationEntries, BerryTranslationEntries, DialogueTranslationEntries, ModifierTypeTranslationEntries, MoveTranslationEntries, PokemonInfoTranslationEntries } from "#app/interfaces/locales"; + +// Module declared to make referencing keys in the localization files type-safe. +declare module "i18next" { + interface CustomTypeOptions { + defaultNS: "menu", // needed here as well for typedoc + resources: { + ability: AbilityTranslationEntries; + abilityTriggers: SimpleTranslationEntries; + achv: AchievementTranslationEntries; + battle: SimpleTranslationEntries; + battleMessageUiHandler: SimpleTranslationEntries; + berry: BerryTranslationEntries; + biome: SimpleTranslationEntries; + challenges: SimpleTranslationEntries; + commandUiHandler: SimpleTranslationEntries; + PGMachv: AchievementTranslationEntries; + PGFachv: AchievementTranslationEntries; + PGMdialogue: DialogueTranslationEntries; + PGFdialogue: DialogueTranslationEntries; + PGMbattleSpecDialogue: SimpleTranslationEntries; + PGFbattleSpecDialogue: SimpleTranslationEntries; + PGMmiscDialogue: SimpleTranslationEntries; + PGFmiscDialogue: SimpleTranslationEntries; + PGMdoubleBattleDialogue: DialogueTranslationEntries; + PGFdoubleBattleDialogue: DialogueTranslationEntries; + egg: SimpleTranslationEntries; + fightUiHandler: SimpleTranslationEntries; + gameMode: SimpleTranslationEntries; + gameStatsUiHandler: SimpleTranslationEntries; + growth: SimpleTranslationEntries; + menu: SimpleTranslationEntries; + menuUiHandler: SimpleTranslationEntries; + modifierType: ModifierTypeTranslationEntries; + move: MoveTranslationEntries; + nature: SimpleTranslationEntries; + partyUiHandler: SimpleTranslationEntries; + pokeball: SimpleTranslationEntries; + pokemon: SimpleTranslationEntries; + pokemonInfo: PokemonInfoTranslationEntries; + pokemonInfoContainer: SimpleTranslationEntries; + saveSlotSelectUiHandler: SimpleTranslationEntries; + settings: SimpleTranslationEntries; + splashMessages: SimpleTranslationEntries; + starterSelectUiHandler: SimpleTranslationEntries; + titles: SimpleTranslationEntries; + trainerClasses: SimpleTranslationEntries; + trainerNames: SimpleTranslationEntries; + tutorial: SimpleTranslationEntries; + voucher: SimpleTranslationEntries; + weather: SimpleTranslationEntries; + }; + } + } diff --git a/src/account.ts b/src/account.ts index e5bde56bfe3..4d19513908f 100644 --- a/src/account.ts +++ b/src/account.ts @@ -7,6 +7,7 @@ export interface UserInfo { } export let loggedInUser: UserInfo = null; +// This is a random string that is used to identify the client session - unique per session (tab or window) so that the game will only save on the one that the server is expecting export const clientSessionId = Utils.randomString(32); export function initLoggedInUser(): void { diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 148b05c59f6..163ca41a406 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -47,7 +47,7 @@ import { biomeDepths, getBiomeName } from "./data/biomes"; import { SceneBase } from "./scene-base"; import CandyBar from "./ui/candy-bar"; import { Variant, variantData } from "./data/variant"; -import { Localizable } from "./plugins/i18n"; +import { Localizable } from "#app/interfaces/locales"; import * as Overrides from "./overrides"; import {InputsController} from "./inputs-controller"; import {UiInputs} from "./ui-inputs"; diff --git a/src/data/ability.ts b/src/data/ability.ts old mode 100755 new mode 100644 index fb84067ac9a..f003bdb48c6 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -14,7 +14,8 @@ import { Stat, getStatName } from "./pokemon-stat"; import { BerryModifier, PokemonHeldItemModifier } from "../modifier/modifier"; import { TerrainType } from "./terrain"; import { SpeciesFormChangeManualTrigger } from "./pokemon-forms"; -import i18next, { Localizable } from "#app/plugins/i18n.js"; +import i18next from "i18next"; +import { Localizable } from "#app/interfaces/locales.js"; import { Command } from "../ui/command-ui-handler"; import { BerryModifierType } from "#app/modifier/modifier-type"; import { getPokeballName } from "./pokeball"; @@ -1044,6 +1045,56 @@ export class PreAttackAbAttr extends AbAttr { } } +/** + * Modifies moves additional effects with multipliers, ie. Sheer Force, Serene Grace. + * @extends AbAttr + * @see {@linkcode apply} + */ +export class MoveEffectChanceMultiplierAbAttr extends AbAttr { + private chanceMultiplier: number; + + constructor(chanceMultiplier?: number) { + super(true); + this.chanceMultiplier = chanceMultiplier; + } + /** + * @param args [0]: {@linkcode Utils.NumberHolder} Move additional effect chance. Has to be higher than or equal to 0. + * [1]: {@linkcode Moves } Move used by the ability user. + */ + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + + if ((args[0] as Utils.NumberHolder).value <= 0 || (args[1] as Move).id === Moves.ORDER_UP) { + return false; + } + + (args[0] as Utils.NumberHolder).value *= this.chanceMultiplier; + (args[0] as Utils.NumberHolder).value = Math.min((args[0] as Utils.NumberHolder).value, 100); + return true; + + } +} + +/** + * Sets incoming moves additional effect chance to zero, ignoring all effects from moves. ie. Shield Dust. + * @extends PreDefendAbAttr + * @see {@linkcode applyPreDefend} + */ +export class IgnoreMoveEffectsAbAttr extends PreDefendAbAttr { + /** + * @param args [0]: {@linkcode Utils.NumberHolder} Move additional effect chance. + */ + applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { + + if ((args[0] as Utils.NumberHolder).value <= 0) { + return false; + } + + (args[0] as Utils.NumberHolder).value = 0; + return true; + + } +} + export class VariableMovePowerAbAttr extends PreAttackAbAttr { applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { //const power = args[0] as Utils.NumberHolder; @@ -1275,17 +1326,18 @@ export class VariableMovePowerBoostAbAttr extends VariableMovePowerAbAttr { } } -export class FieldVariableMovePowerAbAttr extends AbAttr { - applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: Move, args: any[]): boolean { - //const power = args[0] as Utils.NumberHolder; - return false; - } -} - -export class FieldMovePowerBoostAbAttr extends FieldVariableMovePowerAbAttr { +/** + * Boosts the power of a Pokémon's move under certain conditions. + * @extends AbAttr + */ +export class FieldMovePowerBoostAbAttr extends AbAttr { private condition: PokemonAttackCondition; private powerMultiplier: number; + /** + * @param condition - A function that determines whether the power boost condition is met. + * @param powerMultiplier - The multiplier to apply to the move's power when the condition is met. + */ constructor(condition: PokemonAttackCondition, powerMultiplier: number) { super(false); this.condition = condition; @@ -1303,12 +1355,34 @@ export class FieldMovePowerBoostAbAttr extends FieldVariableMovePowerAbAttr { } } +/** + * Boosts the power of a specific type of move. + * @extends FieldMovePowerBoostAbAttr + */ export class FieldMoveTypePowerBoostAbAttr extends FieldMovePowerBoostAbAttr { + /** + * @param boostedType - The type of move that will receive the power boost. + * @param powerMultiplier - The multiplier to apply to the move's power, defaults to 1.5 if not provided. + */ constructor(boostedType: Type, powerMultiplier?: number) { super((pokemon, defender, move) => move.type === boostedType, powerMultiplier || 1.5); } } +/** + * Boosts the power of moves in specified categories. + * @extends FieldMovePowerBoostAbAttr + */ +export class AllyMoveCategoryPowerBoostAbAttr extends FieldMovePowerBoostAbAttr { + /** + * @param boostedCategories - The categories of moves that will receive the power boost. + * @param powerMultiplier - The multiplier to apply to the move's power. + */ + constructor(boostedCategories: MoveCategory[], powerMultiplier: number) { + super((pokemon, defender, move) => boostedCategories.includes(move.category), powerMultiplier); + } +} + export class BattleStatMultiplierAbAttr extends AbAttr { private battleStat: BattleStat; private multiplier: number; @@ -1387,7 +1461,8 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { } applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { + /**Status inflicted by abilities post attacking are also considered additional effects.*/ + if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; return attacker.trySetStatus(effect, true, pokemon); } @@ -1417,10 +1492,9 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { } applyPostAttack(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) { + /**Battler tags inflicted by abilities post attacking are also considered additional effects.*/ + if (!attacker.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr) && pokemon !== attacker && (!this.contactRequired || move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) && pokemon.randSeedInt(100) < this.chance(attacker, pokemon, move) && !pokemon.status) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - - return attacker.addTag(effect); } @@ -1625,6 +1699,28 @@ export class PostSummonAbAttr extends AbAttr { return false; } } +/** + * Removes specified arena tags when a Pokemon is summoned. + */ +export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr { + private arenaTags: ArenaTagType[]; + + /** + * @param arenaTags {@linkcode ArenaTagType[]} - the arena tags to be removed + */ + constructor(arenaTags: ArenaTagType[]) { + super(true); + + this.arenaTags = arenaTags; + } + + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise { + for (const arenaTag of this.arenaTags) { + pokemon.scene.arena.removeTag(arenaTag); + } + return true; + } +} export class PostSummonMessageAbAttr extends PostSummonAbAttr { private messageFunc: (pokemon: Pokemon) => string; @@ -2349,6 +2445,35 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr { } } +/** + * Condition function to applied to abilities related to Sheer Force. + * Checks if last move used against target was affected by a Sheer Force user and: + * Disables: Color Change, Pickpocket, Wimp Out, Emergency Exit, Berserk, Anger Shell + * @returns {AbAttrCondition} If false disables the ability which the condition is applied to. + */ +function getSheerForceHitDisableAbCondition(): AbAttrCondition { + return (pokemon: Pokemon) => { + if (!pokemon.turnData) { + return true; + } + + const lastReceivedAttack = pokemon.turnData.attacksReceived[0]; + if (!lastReceivedAttack) { + return true; + } + + const lastAttacker = pokemon.getOpponents().find(p => p.id === lastReceivedAttack.sourceId); + if (!lastAttacker) { + return true; + } + + /**if the last move chance is greater than or equal to cero, and the last attacker's ability is sheer force*/ + const SheerForceAffected = allMoves[lastReceivedAttack.move].chance >= 0 && lastAttacker.hasAbility(Abilities.SHEER_FORCE); + + return !SheerForceAffected; + }; +} + function getWeatherCondition(...weatherTypes: WeatherType[]): AbAttrCondition { return (pokemon: Pokemon) => { if (pokemon.scene.arena.weather?.isEffectSuppressed(pokemon.scene)) { @@ -3925,7 +4050,8 @@ export function initAbilities() { .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .ignorable(), new Ability(Abilities.COLOR_CHANGE, 3) - .attr(PostDefendTypeChangeAbAttr), + .attr(PostDefendTypeChangeAbAttr) + .condition(getSheerForceHitDisableAbCondition()), new Ability(Abilities.IMMUNITY, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .ignorable(), @@ -3933,8 +4059,8 @@ export function initAbilities() { .attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1, (pokemon: Pokemon) => !pokemon.status || pokemon.status.effect !== StatusEffect.FREEZE) .ignorable(), new Ability(Abilities.SHIELD_DUST, 3) - .ignorable() - .unimplemented(), + .attr(IgnoreMoveEffectsAbAttr) + .partial(), new Ability(Abilities.OWN_TEMPO, 3) .attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED) .attr(IntimidateImmunityAbAttr) @@ -3977,7 +4103,8 @@ export function initAbilities() { .attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPATK, 1) .ignorable(), new Ability(Abilities.SERENE_GRACE, 3) - .unimplemented(), + .attr(MoveEffectChanceMultiplierAbAttr, 2) + .partial(), new Ability(Abilities.SWIFT_SWIM, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)), @@ -4253,9 +4380,12 @@ export function initAbilities() { new Ability(Abilities.BAD_DREAMS, 4) .attr(PostTurnHurtIfSleepingAbAttr), new Ability(Abilities.PICKPOCKET, 5) - .attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT)), + .attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT)) + .condition(getSheerForceHitDisableAbCondition()), new Ability(Abilities.SHEER_FORCE, 5) - .unimplemented(), + .attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461/4096) + .attr(MoveEffectChanceMultiplierAbAttr, 0) + .partial(), new Ability(Abilities.CONTRARY, 5) .attr(StatChangeMultiplierAbAttr, -1) .ignorable(), @@ -4464,8 +4594,10 @@ export function initAbilities() { new Ability(Abilities.STAMINA, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.DEF, 1), new Ability(Abilities.WIMP_OUT, 7) + .condition(getSheerForceHitDisableAbCondition()) .unimplemented(), new Ability(Abilities.EMERGENCY_EXIT, 7) + .condition(getSheerForceHitDisableAbCondition()) .unimplemented(), new Ability(Abilities.WATER_COMPACTION, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.WATER && move.category !== MoveCategory.STATUS, BattleStat.DEF, 2), @@ -4491,7 +4623,8 @@ export function initAbilities() { new Ability(Abilities.STEELWORKER, 7) .attr(MoveTypePowerBoostAbAttr, Type.STEEL), new Ability(Abilities.BERSERK, 7) - .attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [BattleStat.SPATK], 1), + .attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [BattleStat.SPATK], 1) + .condition(getSheerForceHitDisableAbCondition()), new Ability(Abilities.SLUSH_RUSH, 7) .attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .condition(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW)), @@ -4565,7 +4698,7 @@ export function initAbilities() { new Ability(Abilities.DANCER, 7) .attr(PostDancingMoveAbAttr), new Ability(Abilities.BATTERY, 7) - .unimplemented(), + .attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL], 1.3), new Ability(Abilities.FLUFFY, 7) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.type === Type.FIRE, 2) @@ -4677,11 +4810,11 @@ export function initAbilities() { .attr(IceFaceMoveImmunityAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE)) .ignorable(), new Ability(Abilities.POWER_SPOT, 8) - .unimplemented(), + .attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3), new Ability(Abilities.MIMICRY, 8) .unimplemented(), new Ability(Abilities.SCREEN_CLEANER, 8) - .unimplemented(), + .attr(PostSummonRemoveArenaTagAbAttr, [ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.REFLECT]), new Ability(Abilities.STEELY_SPIRIT, 8) .attr(MoveTypePowerBoostAbAttr, Type.STEEL) .partial(), @@ -4750,7 +4883,8 @@ export function initAbilities() { .ignorable(), new Ability(Abilities.ANGER_SHELL, 9) .attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ BattleStat.ATK, BattleStat.SPATK, BattleStat.SPD ], 1) - .attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ BattleStat.DEF, BattleStat.SPDEF ], -1), + .attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ BattleStat.DEF, BattleStat.SPDEF ], -1) + .condition(getSheerForceHitDisableAbCondition()), new Ability(Abilities.PURIFYING_SALT, 9) .attr(StatusEffectImmunityAbAttr) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.GHOST, 0.5) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index b1c1b46487c..81ba4b17005 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -633,6 +633,11 @@ export class GravityTag extends ArenaTag { onAdd(arena: Arena): void { arena.scene.queueMessage("Gravity intensified!"); + arena.scene.getField(true).forEach((pokemon) => { + if (pokemon !== null) { + pokemon.removeTag(BattlerTagType.MAGNET_RISEN); + } + }); } onRemove(arena: Arena): void { diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 977dceb8d30..db02803c5ea 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -1009,6 +1009,33 @@ export class PerishSongTag extends BattlerTag { } } +/** + * Applies the "Center of Attention" volatile status effect, the effect applied by Follow Me, Rage Powder, and Spotlight. + * @see {@link https://bulbapedia.bulbagarden.net/wiki/Center_of_attention | Center of Attention} + */ +export class CenterOfAttentionTag extends BattlerTag { + public powder: boolean; + + constructor(sourceMove: Moves) { + super(BattlerTagType.CENTER_OF_ATTENTION, BattlerTagLapseType.TURN_END, 1, sourceMove); + + this.powder = (this.sourceMove === Moves.RAGE_POWDER); + } + + /** "Center of Attention" can't be added if an ally is already the Center of Attention. */ + canAdd(pokemon: Pokemon): boolean { + const activeTeam = pokemon.isPlayer() ? pokemon.scene.getPlayerField() : pokemon.scene.getEnemyField(); + + return !activeTeam.find(p => p.getTag(BattlerTagType.CENTER_OF_ATTENTION)); + } + + onAdd(pokemon: Pokemon): void { + super.onAdd(pokemon); + + pokemon.scene.queueMessage(getPokemonMessage(pokemon, " became the center\nof attention!")); + } +} + export class AbilityBattlerTag extends BattlerTag { public ability: Abilities; @@ -1187,8 +1214,11 @@ export class HideSpriteTag extends BattlerTag { export class TypeImmuneTag extends BattlerTag { public immuneType: Type; - constructor(tagType: BattlerTagType, sourceMove: Moves, immuneType: Type, length: number) { - super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove); + + constructor(tagType: BattlerTagType, sourceMove: Moves, immuneType: Type, length: number = 1) { + super(tagType, BattlerTagLapseType.TURN_END, length, sourceMove); + + this.immuneType = immuneType; } /** @@ -1205,6 +1235,18 @@ export class MagnetRisenTag extends TypeImmuneTag { constructor(tagType: BattlerTagType, sourceMove: Moves) { super(tagType, sourceMove, Type.GROUND, 5); } + + onAdd(pokemon: Pokemon): void { + super.onAdd(pokemon); + + pokemon.scene.queueMessage(getPokemonMessage(pokemon, " levitated with electromagnetism!")); + } + + onRemove(pokemon: Pokemon): void { + super.onRemove(pokemon); + + pokemon.scene.queueMessage(getPokemonMessage(pokemon, " stopped levitating!")); + } } export class TypeBoostTag extends BattlerTag { @@ -1479,6 +1521,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new SturdyTag(sourceMove); case BattlerTagType.PERISH_SONG: return new PerishSongTag(turnCount); + case BattlerTagType.CENTER_OF_ATTENTION: + return new CenterOfAttentionTag(sourceMove); case BattlerTagType.TRUANT: return new TruantTag(); case BattlerTagType.SLOW_START: diff --git a/src/data/berry.ts b/src/data/berry.ts index 5b4f55c8e13..4e0d1dbd85f 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -5,7 +5,7 @@ import { BattleStat } from "./battle-stat"; import { getStatusEffectHealText } from "./status-effect"; import * as Utils from "../utils"; import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 8b41e8c8d9d..5c689ef7345 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -1,12 +1,14 @@ import * as Utils from "../utils"; -import i18next from "#app/plugins/i18n.js"; -import { GameData } from "#app/system/game-data.js"; -import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species"; +import i18next from "i18next"; +import { DexAttrProps, GameData } from "#app/system/game-data.js"; +import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species"; import Pokemon from "#app/field/pokemon.js"; import { BattleType, FixedBattleConfig } from "#app/battle.js"; import Trainer, { TrainerVariant } from "#app/field/trainer.js"; import { GameMode } from "#app/game-mode.js"; import { Type } from "./type"; +import { pokemonEvolutions } from "./pokemon-evolutions"; +import { pokemonFormChanges } from "./pokemon-forms"; import { Challenges } from "#enums/challenges"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; @@ -277,8 +279,22 @@ export class SingleGenerationChallenge extends Challenge { case ChallengeType.STARTER_CHOICE: const species = args[0] as PokemonSpecies; const isValidStarter = args[1] as Utils.BooleanHolder; + const amountOfPokemon = args[3] as number; const starterGeneration = species.speciesId === Species.VICTINI ? 5 : species.generation; - if (starterGeneration !== this.value) { + const generations = [starterGeneration]; + if (amountOfPokemon > 0) { + const speciesToCheck = [species.speciesId]; + while (speciesToCheck.length) { + const checking = speciesToCheck.pop(); + if (pokemonEvolutions.hasOwnProperty(checking)) { + pokemonEvolutions[checking].forEach(e => { + speciesToCheck.push(e.speciesId); + generations.push(getPokemonSpecies(e.speciesId).generation); + }); + } + } + } + if (!generations.includes(this.value)) { isValidStarter.value = false; return true; } @@ -372,7 +388,32 @@ export class SingleTypeChallenge extends Challenge { case ChallengeType.STARTER_CHOICE: const species = args[0] as PokemonSpecies; const isValidStarter = args[1] as Utils.BooleanHolder; - if (!species.isOfType(this.value - 1)) { + const dexAttr = args[2] as DexAttrProps; + const amountOfPokemon = args[3] as number; + const speciesForm = getPokemonSpeciesForm(species.speciesId, dexAttr.formIndex); + const types = [speciesForm.type1, speciesForm.type2]; + if (amountOfPokemon > 0) { + const speciesToCheck = [species.speciesId]; + while (speciesToCheck.length) { + const checking = speciesToCheck.pop(); + if (pokemonEvolutions.hasOwnProperty(checking)) { + pokemonEvolutions[checking].forEach(e => { + speciesToCheck.push(e.speciesId); + types.push(getPokemonSpecies(e.speciesId).type1, getPokemonSpecies(e.speciesId).type2); + }); + } + if (pokemonFormChanges.hasOwnProperty(checking)) { + pokemonFormChanges[checking].forEach(f1 => { + getPokemonSpecies(checking).forms.forEach(f2 => { + if (f1.formKey === f2.formKey) { + types.push(f2.type1, f2.type2); + } + }); + }); + } + } + } + if (!types.includes(this.value - 1)) { isValidStarter.value = false; return true; } @@ -535,7 +576,7 @@ export class LowerStarterPointsChallenge extends Challenge { /** * Apply all challenges of a given challenge type. - * @param {BattleScene} scene The current scene + * @param {GameMode} gameMode The current game mode * @param {ChallengeType} challengeType What challenge type to apply * @param {any[]} args Any args for that challenge type * @returns {boolean} True if any challenge was successfully applied. diff --git a/src/data/egg.ts b/src/data/egg.ts index 1c3c0e78798..ec82143e727 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -1,6 +1,6 @@ import BattleScene from "../battle-scene"; import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { EggTier } from "#enums/egg-type"; import { Species } from "#enums/species"; diff --git a/src/data/move.ts b/src/data/move.ts index 8571ac69562..7f0d9187847 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -9,7 +9,7 @@ import { Type } from "./type"; import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; -import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, ForceSwitchOutImmunityAbAttr } from "./ability"; +import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, ForceSwitchOutImmunityAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr } from "./ability"; import { allAbilities } from "./ability"; import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier } from "../modifier/modifier"; import { BattlerIndex } from "../battle"; @@ -18,7 +18,8 @@ import { TerrainType } from "./terrain"; import { SpeciesFormChangeActiveTrigger } from "./pokemon-forms"; import { ModifierPoolType } from "#app/modifier/modifier-type"; import { Command } from "../ui/command-ui-handler"; -import i18next, { Localizable } from "../plugins/i18n"; +import i18next from "i18next"; +import { Localizable } from "#app/interfaces/locales"; import { getBerryEffectFunc } from "./berry"; import { Abilities } from "#enums/abilities"; import { ArenaTagType } from "#enums/arena-tag-type"; @@ -277,18 +278,29 @@ export default class Move implements Localizable { } /** - * Checks if the move is immune to certain types - * currently only look at case of Grass types and powder moves - * @param type {@linkcode Type} enum + * Checks if the move is immune to certain types. + * Currently looks at cases of Grass types with powder moves and Dark types with moves affected by Prankster. + * @param {Pokemon} user the source of this move + * @param {Pokemon} target the target of this move + * @param {Type} type the type of the move's target * @returns boolean */ - isTypeImmune(type: Type): boolean { + isTypeImmune(user: Pokemon, target: Pokemon, type: Type): boolean { + if (this.moveTarget === MoveTarget.USER) { + return false; + } + switch (type) { case Type.GRASS: if (this.hasFlag(MoveFlags.POWDER_MOVE)) { return true; } break; + case Type.DARK: + if (user.hasAbility(Abilities.PRANKSTER) && this.category === MoveCategory.STATUS && (user.isPlayer() !== target.isPlayer())) { + return true; + } + break; } return false; } @@ -793,7 +805,7 @@ export enum MoveEffectTrigger { */ export class MoveEffectAttr extends MoveAttr { /** Defines when this effect should trigger in the move's effect order - * @see {@linkcode MoveEffectPhase.start} + * @see {@linkcode phases.MoveEffectPhase.start} */ public trigger: MoveEffectTrigger; /** Should this effect only apply on the first hit? */ @@ -824,6 +836,22 @@ export class MoveEffectAttr extends MoveAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { return this.canApply(user, target, move, args); } + + /** + * Gets the used move's additional effect chance. + * If user's ability has MoveEffectChanceMultiplierAbAttr or IgnoreMoveEffectsAbAttr modifies the base chance. + * @param user {@linkcode Pokemon} using this move + * @param target {@linkcode Pokemon} target of this move + * @param move {@linkcode Move} being used + * @param selfEffect {@linkcode Boolean} if move targets user. + * @returns Move chance value. + */ + getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean): integer { + const moveChance = new Utils.NumberHolder(move.chance); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, moveChance, move, target, selfEffect); + applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr,target,user,null,null, moveChance); + return moveChance.value; + } } export class PreMoveMessageAttr extends MoveAttr { @@ -1668,7 +1696,8 @@ export class StatusEffectAttr extends MoveEffectAttr { } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const statusCheck = move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance; + const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + const statusCheck = moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance; if (statusCheck) { const pokemon = this.selfTarget ? user : target; if (pokemon.status) { @@ -1678,7 +1707,7 @@ export class StatusEffectAttr extends MoveEffectAttr { return false; } } - if ((!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0)) + if ((!pokemon.status || (pokemon.status.effect === this.effect && moveChance < 0)) && pokemon.trySetStatus(this.effect, true, user, this.cureTurn)) { applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null,this.effect); return true; @@ -1688,7 +1717,8 @@ export class StatusEffectAttr extends MoveEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { - return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(this.effect, true, false, user) ? Math.floor(move.chance * -0.1) : 0; + const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(this.effect, true, false, user) ? Math.floor(moveChance * -0.1) : 0; } } @@ -1707,7 +1737,8 @@ export class MultiStatusEffectAttr extends StatusEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { - return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(this.effect, true, false, user) ? Math.floor(move.chance * -0.1) : 0; + const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + return !(this.selfTarget ? user : target).status && (this.selfTarget ? user : target).canSetStatus(this.effect, true, false, user) ? Math.floor(moveChance * -0.1) : 0; } } @@ -2310,7 +2341,8 @@ export class StatChangeAttr extends MoveEffectAttr { return false; } - if (move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) { + const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { const levels = this.getLevels(user); user.scene.unshiftPhase(new StatChangePhase(user.scene, (this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, levels, this.showMessage)); return true; @@ -3034,10 +3066,8 @@ export class FriendshipPowerAttr extends VariablePowerAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const power = args[0] as Utils.NumberHolder; - if (user instanceof PlayerPokemon) { - const friendshipPower = Math.floor(Math.min(user.friendship, 255) / 2.5); - power.value = Math.max(!this.invert ? friendshipPower : 102 - friendshipPower, 1); - } + const friendshipPower = Math.floor(Math.min(user instanceof PlayerPokemon ? user.friendship : user.species.baseFriendship, 255) / 2.5); + power.value = Math.max(!this.invert ? friendshipPower : 102 - friendshipPower, 1); return true; } @@ -3889,18 +3919,14 @@ export class AddBattlerTagAttr extends MoveEffectAttr { return false; } - const chance = this.getTagChance(user, target, move); - if (chance < 0 || chance === 100 || user.randSeedInt(100) < chance) { + const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { return (this.selfTarget ? user : target).addTag(this.tagType, user.randSeedInt(this.turnCountMax - this.turnCountMin, this.turnCountMin), move.id, user.id); } return false; } - getTagChance(user: Pokemon, target: Pokemon, move: Move): integer { - return move.chance; - } - getCondition(): MoveConditionFunc { return this.failOnOverlap ? (user, target, move) => !(this.selfTarget ? user : target).getTag(this.tagType) @@ -3950,11 +3976,11 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { - let chance = this.getTagChance(user, target, move); - if (chance < 0) { - chance = 100; + let moveChance = this.getMoveChance(user,target,move,this.selfTarget); + if (moveChance < 0) { + moveChance = 100; } - return Math.floor(this.getTagTargetBenefitScore(user, target, move) * (chance / 100)); + return Math.floor(this.getTagTargetBenefitScore(user, target, move) * (moveChance / 100)); } } @@ -4219,15 +4245,42 @@ export class AddArenaTrapTagAttr extends AddArenaTagAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; - if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, side)) { + const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; + if (!tag) { return true; } - const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; return tag.layers < tag.maxLayers; }; } } +/** + * Attribute used for Stone Axe and Ceaseless Edge. + * Applies the given ArenaTrapTag when move is used. + * @extends AddArenaTagAttr + * @see {@linkcode apply} + */ +export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { + /** + * @param user {@linkcode Pokemon} using this move + * @param target {@linkcode Pokemon} target of this move + * @param move {@linkcode Move} being used + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; + const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; + if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance)) { + user.scene.arena.addTag(this.tagType, 0, move.id, user.id, side); + if (!tag) { + return true; + } + return tag.layers < tag.maxLayers; + } + return false; + } +} + export class RemoveArenaTrapAttr extends MoveEffectAttr { private targetBothSides: boolean; @@ -4553,7 +4606,7 @@ export class RemoveTypeAttr extends MoveEffectAttr { export class CopyTypeAttr extends MoveEffectAttr { constructor() { - super(true); + super(false); } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { @@ -4919,14 +4972,36 @@ export class CopyMoveAttr extends OverrideMoveEffectAttr { } } +/** + * Attribute used for moves that reduce PP of the target's last used move. + * Used for Spite. + */ export class ReducePpMoveAttr extends MoveEffectAttr { + protected reduction: number; + constructor(reduction: number) { + super(); + this.reduction = reduction; + } + + /** + * Reduces the PP of the target's last-used move by an amount based on this attribute instance's {@linkcode reduction}. + * + * @param user {@linkcode Pokemon} that used the attack + * @param target {@linkcode Pokemon} targeted by the attack + * @param move {@linkcode Move} being used + * @param args N/A + * @returns {boolean} true + */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { // Null checks can be skipped due to condition function const lastMove = target.getLastXMoves().find(() => true); const movesetMove = target.getMoveset().find(m => m.moveId === lastMove.move); const lastPpUsed = movesetMove.ppUsed; - movesetMove.ppUsed = Math.min(movesetMove.ppUsed + 4, movesetMove.getMovePp()); - user.scene.queueMessage(`It reduced the PP of ${getPokemonMessage(target, `'s\n${movesetMove.getName()} by ${movesetMove.ppUsed - lastPpUsed}!`)}`); + movesetMove.ppUsed = Math.min(movesetMove.ppUsed + this.reduction, movesetMove.getMovePp()); + + const message = i18next.t("battle:ppReduced", {targetName: target.name, moveName: movesetMove.getName(), reduction: movesetMove.ppUsed - lastPpUsed}); + + user.scene.queueMessage(message); return true; } @@ -4961,6 +5036,42 @@ export class ReducePpMoveAttr extends MoveEffectAttr { } } +/** + * Attribute used for moves that damage target, and then reduce PP of the target's last used move. + * Used for Eerie Spell. + */ +export class AttackReducePpMoveAttr extends ReducePpMoveAttr { + constructor(reduction: number) { + super(reduction); + } + + /** + * Checks if the target has used a move prior to the attack. PP-reduction is applied through the super class if so. + * + * @param user {@linkcode Pokemon} that used the attack + * @param target {@linkcode Pokemon} targeted by the attack + * @param move {@linkcode Move} being used + * @param args N/A + * @returns {boolean} true + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const lastMove = target.getLastXMoves().find(() => true); + if (lastMove) { + const movesetMove = target.getMoveset().find(m => m.moveId === lastMove.move); + if (Boolean(movesetMove?.getPpRatio())) { + super.apply(user, target, move, args); + } + } + + return true; + } + + // Override condition function to always perform damage. Instead, perform pp-reduction condition check in apply function above + getCondition(): MoveConditionFunc { + return (user, target, move) => true; + } +} + // TODO: Review this const targetMoveCopiableCondition: MoveConditionFunc = (user, target, move) => { const targetMoves = target.getMoveHistory().filter(m => !m.virtual); @@ -5546,7 +5657,7 @@ export function initMoves() { .attr(ChargeAttr, ChargeAnim.FLY_CHARGING, "flew\nup high!", BattlerTagType.FLYING) .condition(failOnGravityCondition) .ignoresVirtual(), - new AttackMove(Moves.BIND, Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, 100, 0, 1) + new AttackMove(Moves.BIND, Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, 0, 1) .attr(TrapAttr, BattlerTagType.BIND), new AttackMove(Moves.SLAM, Type.NORMAL, MoveCategory.PHYSICAL, 80, 75, 20, -1, 0, 1), new AttackMove(Moves.VINE_WHIP, Type.GRASS, MoveCategory.PHYSICAL, 45, 100, 25, -1, 0, 1), @@ -5579,7 +5690,7 @@ export function initMoves() { .attr(MinimizeAccuracyAttr) .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), - new AttackMove(Moves.WRAP, Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, 100, 0, 1) + new AttackMove(Moves.WRAP, Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, -1, 0, 1) .attr(TrapAttr, BattlerTagType.WRAP), new AttackMove(Moves.TAKE_DOWN, Type.NORMAL, MoveCategory.PHYSICAL, 90, 85, 20, -1, 0, 1) .attr(RecoilAttr) @@ -5604,7 +5715,7 @@ export function initMoves() { new AttackMove(Moves.PIN_MISSILE, Type.BUG, MoveCategory.PHYSICAL, 25, 95, 20, -1, 0, 1) .attr(MultiHitAttr) .makesContact(false), - new StatusMove(Moves.LEER, Type.NORMAL, 100, 30, 100, 0, 1) + new StatusMove(Moves.LEER, Type.NORMAL, 100, 30, -1, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, -1) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BITE, Type.DARK, MoveCategory.PHYSICAL, 60, 100, 25, 30, 0, 1) @@ -5713,7 +5824,7 @@ export function initMoves() { .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.DRAGON_RAGE, Type.DRAGON, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 1) .attr(FixedDamageAttr, 40), - new AttackMove(Moves.FIRE_SPIN, Type.FIRE, MoveCategory.SPECIAL, 35, 85, 15, 100, 0, 1) + new AttackMove(Moves.FIRE_SPIN, Type.FIRE, MoveCategory.SPECIAL, 35, 85, 15, -1, 0, 1) .attr(TrapAttr, BattlerTagType.FIRE_SPIN), new AttackMove(Moves.THUNDER_SHOCK, Type.ELECTRIC, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), @@ -5828,11 +5939,11 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.BURN), new AttackMove(Moves.WATERFALL, Type.WATER, MoveCategory.PHYSICAL, 80, 100, 15, 20, 0, 1) .attr(FlinchAttr), - new AttackMove(Moves.CLAMP, Type.WATER, MoveCategory.PHYSICAL, 35, 85, 15, 100, 0, 1) + new AttackMove(Moves.CLAMP, Type.WATER, MoveCategory.PHYSICAL, 35, 85, 15, -1, 0, 1) .attr(TrapAttr, BattlerTagType.CLAMP), new AttackMove(Moves.SWIFT, Type.NORMAL, MoveCategory.SPECIAL, 60, -1, 20, -1, 0, 1) .target(MoveTarget.ALL_NEAR_ENEMIES), - new AttackMove(Moves.SKULL_BASH, Type.NORMAL, MoveCategory.PHYSICAL, 130, 100, 10, 100, 0, 1) + new AttackMove(Moves.SKULL_BASH, Type.NORMAL, MoveCategory.PHYSICAL, 130, 100, 10, -1, 0, 1) .attr(ChargeAttr, ChargeAnim.SKULL_BASH_CHARGING, "lowered\nits head!", null, true) .attr(StatChangeAttr, BattleStat.DEF, 1, true) .ignoresVirtual(), @@ -5980,7 +6091,7 @@ export function initMoves() { new AttackMove(Moves.REVERSAL, Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 15, -1, 0, 2) .attr(LowHpPowerAttr), new StatusMove(Moves.SPITE, Type.GHOST, 100, 10, -1, 0, 2) - .attr(ReducePpMoveAttr), + .attr(ReducePpMoveAttr, 4), new AttackMove(Moves.POWDER_SNOW, Type.ICE, MoveCategory.SPECIAL, 40, 100, 25, 10, 0, 2) .attr(StatusEffectAttr, StatusEffect.FREEZE) .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -6180,7 +6291,7 @@ export function initMoves() { .attr(DelayedAttackAttr, ArenaTagType.FUTURE_SIGHT, ChargeAnim.FUTURE_SIGHT_CHARGING, "foresaw\nan attack!"), new AttackMove(Moves.ROCK_SMASH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 15, 50, 0, 2) .attr(StatChangeAttr, BattleStat.DEF, -1), - new AttackMove(Moves.WHIRLPOOL, Type.WATER, MoveCategory.SPECIAL, 35, 85, 15, 100, 0, 2) + new AttackMove(Moves.WHIRLPOOL, Type.WATER, MoveCategory.SPECIAL, 35, 85, 15, -1, 0, 2) .attr(TrapAttr, BattlerTagType.WHIRLPOOL) .attr(HitsTagAttr, BattlerTagType.UNDERWATER, true), new AttackMove(Moves.BEAT_UP, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 2) @@ -6232,7 +6343,7 @@ export function initMoves() { .attr(MovePowerMultiplierAttr, (user, target, move) => target.status?.effect === StatusEffect.PARALYSIS ? 2 : 1) .attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS), new SelfStatusMove(Moves.FOLLOW_ME, Type.NORMAL, -1, 20, -1, 2, 3) - .unimplemented(), + .attr(AddBattlerTagAttr, BattlerTagType.CENTER_OF_ATTENTION, true), new StatusMove(Moves.NATURE_POWER, Type.NORMAL, -1, 20, -1, 0, 3) .attr(NaturePowerAttr) .ignoresVirtual(), @@ -6256,7 +6367,7 @@ export function initMoves() { .ignoresVirtual(), new SelfStatusMove(Moves.INGRAIN, Type.GRASS, -1, 20, -1, 0, 3) .attr(AddBattlerTagAttr, BattlerTagType.INGRAIN, true, true), - new AttackMove(Moves.SUPERPOWER, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, 100, 0, 3) + new AttackMove(Moves.SUPERPOWER, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 3) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF ], -1, true), new SelfStatusMove(Moves.MAGIC_COAT, Type.PSYCHIC, -1, 15, -1, 4, 3) .unimplemented(), @@ -6358,7 +6469,7 @@ export function initMoves() { .slicingMove() .windMove() .target(MoveTarget.ALL_NEAR_ENEMIES), - new AttackMove(Moves.OVERHEAT, Type.FIRE, MoveCategory.SPECIAL, 130, 90, 5, 100, 0, 3) + new AttackMove(Moves.OVERHEAT, Type.FIRE, MoveCategory.SPECIAL, 130, 90, 5, -1, 0, 3) .attr(StatChangeAttr, BattleStat.SPATK, -2, true) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE), new StatusMove(Moves.ODOR_SLEUTH, Type.NORMAL, -1, 40, -1, 0, 3) @@ -6391,7 +6502,7 @@ export function initMoves() { new AttackMove(Moves.SKY_UPPERCUT, Type.FIGHTING, MoveCategory.PHYSICAL, 85, 90, 15, -1, 0, 3) .attr(HitsTagAttr, BattlerTagType.FLYING) .punchingMove(), - new AttackMove(Moves.SAND_TOMB, Type.GROUND, MoveCategory.PHYSICAL, 35, 85, 15, 100, 0, 3) + new AttackMove(Moves.SAND_TOMB, Type.GROUND, MoveCategory.PHYSICAL, 35, 85, 15, -1, 0, 3) .attr(TrapAttr, BattlerTagType.SAND_TOMB) .makesContact(false), new AttackMove(Moves.SHEER_COLD, Type.ICE, MoveCategory.SPECIAL, 200, 20, 5, -1, 0, 3) @@ -6461,7 +6572,7 @@ export function initMoves() { .pulseMove(), new AttackMove(Moves.DOOM_DESIRE, Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, 0, 3) .attr(DelayedAttackAttr, ArenaTagType.DOOM_DESIRE, ChargeAnim.DOOM_DESIRE_CHARGING, "chose\nDoom Desire as its destiny!"), - new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, 100, 0, 3) + new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, 0, 3) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new SelfStatusMove(Moves.ROOST, Type.FLYING, -1, 5, -1, 0, 4) .attr(HealAttr, 0.5) @@ -6475,7 +6586,7 @@ export function initMoves() { new AttackMove(Moves.WAKE_UP_SLAP, Type.FIGHTING, MoveCategory.PHYSICAL, 70, 100, 10, -1, 0, 4) .attr(MovePowerMultiplierAttr, (user, target, move) => targetSleptOrComatoseCondition(user, target, move) ? 2 : 1) .attr(HealStatusEffectAttr, false, StatusEffect.SLEEP), - new AttackMove(Moves.HAMMER_ARM, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 90, 10, 100, 0, 4) + new AttackMove(Moves.HAMMER_ARM, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 90, 10, -1, 0, 4) .attr(StatChangeAttr, BattleStat.SPD, -1, true) .punchingMove(), new AttackMove(Moves.GYRO_BALL, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4) @@ -6509,7 +6620,7 @@ export function initMoves() { .target(MoveTarget.ATTACKER), new AttackMove(Moves.U_TURN, Type.BUG, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 4) .attr(ForceSwitchOutAttr, true, false), - new AttackMove(Moves.CLOSE_COMBAT, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, 100, 0, 4) + new AttackMove(Moves.CLOSE_COMBAT, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 4) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], -1, true), new AttackMove(Moves.PAYBACK, Type.DARK, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 4) .attr(MovePowerMultiplierAttr, (user, target, move) => target.getLastXMoves(1).find(m => m.turn === target.scene.currentBattle.turn) || user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.BALL ? 2 : 1), @@ -6553,9 +6664,9 @@ export function initMoves() { new SelfStatusMove(Moves.COPYCAT, Type.NORMAL, -1, 20, -1, 0, 4) .attr(CopyMoveAttr) .ignoresVirtual(), - new StatusMove(Moves.POWER_SWAP, Type.PSYCHIC, -1, 10, -1, 0, 4) + new StatusMove(Moves.POWER_SWAP, Type.PSYCHIC, -1, 10, 100, 0, 4) .unimplemented(), - new StatusMove(Moves.GUARD_SWAP, Type.PSYCHIC, -1, 10, -1, 0, 4) + new StatusMove(Moves.GUARD_SWAP, Type.PSYCHIC, -1, 10, 100, 0, 4) .unimplemented(), new AttackMove(Moves.PUNISHMENT, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4) .makesContact(true) @@ -6575,10 +6686,7 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.AQUA_RING, true, true), new SelfStatusMove(Moves.MAGNET_RISE, Type.ELECTRIC, -1, 10, -1, 0, 4) .attr(AddBattlerTagAttr, BattlerTagType.MAGNET_RISEN, true, true) - .condition((user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY) && - !user.getTag(BattlerTagType.IGNORE_FLYING) && !user.getTag(BattlerTagType.INGRAIN) && - !user.getTag(BattlerTagType.MAGNET_RISEN)) - .unimplemented(), + .condition((user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY) && [BattlerTagType.MAGNET_RISEN, BattlerTagType.IGNORE_FLYING, BattlerTagType.INGRAIN].every((tag) => !user.getTag(tag))), new AttackMove(Moves.FLARE_BLITZ, Type.FIRE, MoveCategory.PHYSICAL, 120, 100, 15, 10, 0, 4) .attr(RecoilAttr, false, 0.33) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) @@ -6686,7 +6794,7 @@ export function initMoves() { .attr(AddArenaTagAttr, ArenaTagType.TRICK_ROOM, 5) .ignoresProtect() .target(MoveTarget.BOTH_SIDES), - new AttackMove(Moves.DRACO_METEOR, Type.DRAGON, MoveCategory.SPECIAL, 130, 90, 5, 100, 0, 4) + new AttackMove(Moves.DRACO_METEOR, Type.DRAGON, MoveCategory.SPECIAL, 130, 90, 5, -1, 0, 4) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new AttackMove(Moves.DISCHARGE, Type.ELECTRIC, MoveCategory.SPECIAL, 80, 100, 15, 30, 0, 4) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) @@ -6694,7 +6802,7 @@ export function initMoves() { new AttackMove(Moves.LAVA_PLUME, Type.FIRE, MoveCategory.SPECIAL, 80, 100, 15, 30, 0, 4) .attr(StatusEffectAttr, StatusEffect.BURN) .target(MoveTarget.ALL_NEAR_OTHERS), - new AttackMove(Moves.LEAF_STORM, Type.GRASS, MoveCategory.SPECIAL, 130, 90, 5, 100, 0, 4) + new AttackMove(Moves.LEAF_STORM, Type.GRASS, MoveCategory.SPECIAL, 130, 90, 5, -1, 0, 4) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new AttackMove(Moves.POWER_WHIP, Type.GRASS, MoveCategory.PHYSICAL, 120, 85, 10, -1, 0, 4), new AttackMove(Moves.ROCK_WRECKER, Type.ROCK, MoveCategory.PHYSICAL, 150, 90, 5, -1, 0, 4) @@ -6764,7 +6872,7 @@ export function initMoves() { .unimplemented(), new AttackMove(Moves.CRUSH_GRIP, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4) .attr(OpponentHighHpPowerAttr), - new AttackMove(Moves.MAGMA_STORM, Type.FIRE, MoveCategory.SPECIAL, 100, 75, 5, 100, 0, 4) + new AttackMove(Moves.MAGMA_STORM, Type.FIRE, MoveCategory.SPECIAL, 100, 75, 5, -1, 0, 4) .attr(TrapAttr, BattlerTagType.MAGMA_STORM), new StatusMove(Moves.DARK_VOID, Type.DARK, 50, 10, -1, 0, 4) .attr(StatusEffectAttr, StatusEffect.SLEEP) @@ -6800,7 +6908,7 @@ export function initMoves() { .partial(), new SelfStatusMove(Moves.RAGE_POWDER, Type.BUG, -1, 20, -1, 2, 5) .powderMove() - .unimplemented(), + .attr(AddBattlerTagAttr, BattlerTagType.CENTER_OF_ATTENTION, true), new StatusMove(Moves.TELEKINESIS, Type.PSYCHIC, -1, 15, -1, 0, 5) .condition(failOnGravityCondition) .unimplemented(), @@ -6811,7 +6919,7 @@ export function initMoves() { new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) - .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING]) + .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN]) .attr(HitsTagAttr, BattlerTagType.FLYING, false) .makesContact(false), new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5) @@ -7024,7 +7132,7 @@ export function initMoves() { new AttackMove(Moves.ICICLE_CRASH, Type.ICE, MoveCategory.PHYSICAL, 85, 90, 10, 30, 0, 5) .attr(FlinchAttr) .makesContact(false), - new AttackMove(Moves.V_CREATE, Type.FIRE, MoveCategory.PHYSICAL, 180, 95, 5, 100, 0, 5) + new AttackMove(Moves.V_CREATE, Type.FIRE, MoveCategory.PHYSICAL, 180, 95, 5, -1, 0, 5) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF, BattleStat.SPD ], -1, true), new AttackMove(Moves.FUSION_FLARE, Type.FIRE, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 5) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) @@ -7043,7 +7151,7 @@ export function initMoves() { .condition(new FirstMoveCondition()), new AttackMove(Moves.BELCH, Type.POISON, MoveCategory.SPECIAL, 120, 90, 10, -1, 0, 6) .condition((user, target, move) => user.battleData.berriesEaten.length > 0), - new StatusMove(Moves.ROTOTILLER, Type.GROUND, -1, 10, 100, 0, 6) + new StatusMove(Moves.ROTOTILLER, Type.GROUND, -1, 10, -1, 0, 6) .target(MoveTarget.ALL) .condition((user,target,move) => { // If any fielded pokémon is grass-type and grounded. @@ -7062,7 +7170,7 @@ export function initMoves() { new StatusMove(Moves.TRICK_OR_TREAT, Type.GHOST, 100, 20, -1, 0, 6) .attr(AddTypeAttr, Type.GHOST) .partial(), - new StatusMove(Moves.NOBLE_ROAR, Type.NORMAL, 100, 30, 100, 0, 6) + new StatusMove(Moves.NOBLE_ROAR, Type.NORMAL, 100, 30, -1, 0, 6) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -1) .soundBased(), new StatusMove(Moves.ION_DELUGE, Type.ELECTRIC, -1, 25, -1, 1, 6) @@ -7085,7 +7193,7 @@ export function initMoves() { new AttackMove(Moves.DISARMING_VOICE, Type.FAIRY, MoveCategory.SPECIAL, 40, -1, 15, -1, 0, 6) .soundBased() .target(MoveTarget.ALL_NEAR_ENEMIES), - new StatusMove(Moves.PARTING_SHOT, Type.DARK, 100, 20, 100, 0, 6) + new StatusMove(Moves.PARTING_SHOT, Type.DARK, 100, 20, -1, 0, 6) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -1, false, null, true, true, MoveEffectTrigger.PRE_APPLY) .attr(ForceSwitchOutAttr, true, false) .soundBased(), @@ -7098,7 +7206,7 @@ export function initMoves() { new StatusMove(Moves.CRAFTY_SHIELD, Type.FAIRY, -1, 10, -1, 3, 6) .target(MoveTarget.USER_SIDE) .attr(AddArenaTagAttr, ArenaTagType.CRAFTY_SHIELD, 1, true, true), - new StatusMove(Moves.FLOWER_SHIELD, Type.FAIRY, -1, 10, 100, 0, 6) + new StatusMove(Moves.FLOWER_SHIELD, Type.FAIRY, -1, 10, -1, 0, 6) .target(MoveTarget.ALL) .unimplemented(), new StatusMove(Moves.GRASSY_TERRAIN, Type.GRASS, -1, 10, -1, 0, 6) @@ -7123,9 +7231,9 @@ export function initMoves() { .unimplemented(), new SelfStatusMove(Moves.KINGS_SHIELD, Type.STEEL, -1, 10, -1, 4, 6) .attr(ProtectAttr, BattlerTagType.KINGS_SHIELD), - new StatusMove(Moves.PLAY_NICE, Type.NORMAL, -1, 20, 100, 0, 6) + new StatusMove(Moves.PLAY_NICE, Type.NORMAL, -1, 20, -1, 0, 6) .attr(StatChangeAttr, BattleStat.ATK, -1), - new StatusMove(Moves.CONFIDE, Type.NORMAL, -1, 20, 100, 0, 6) + new StatusMove(Moves.CONFIDE, Type.NORMAL, -1, 20, -1, 0, 6) .attr(StatChangeAttr, BattleStat.SPATK, -1) .soundBased(), new AttackMove(Moves.DIAMOND_STORM, Type.ROCK, MoveCategory.PHYSICAL, 100, 95, 5, 50, 0, 6) @@ -7151,7 +7259,7 @@ export function initMoves() { .target(MoveTarget.NEAR_ALLY), new StatusMove(Moves.EERIE_IMPULSE, Type.ELECTRIC, 100, 15, -1, 0, 6) .attr(StatChangeAttr, BattleStat.SPATK, -2), - new StatusMove(Moves.VENOM_DRENCH, Type.POISON, 100, 20, 100, 0, 6) + new StatusMove(Moves.VENOM_DRENCH, Type.POISON, 100, 20, -1, 0, 6) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK, BattleStat.SPD ], -1, false, (user, target, move) => target.status?.effect === StatusEffect.POISON || target.status?.effect === StatusEffect.TOXIC) .target(MoveTarget.ALL_NEAR_ENEMIES), new StatusMove(Moves.POWDER, Type.BUG, 100, 20, -1, 1, 6) @@ -7182,7 +7290,7 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new AttackMove(Moves.HOLD_BACK, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 6) .attr(SurviveDamageAttr), - new AttackMove(Moves.INFESTATION, Type.BUG, MoveCategory.SPECIAL, 20, 100, 20, 100, 0, 6) + new AttackMove(Moves.INFESTATION, Type.BUG, MoveCategory.SPECIAL, 20, 100, 20, -1, 0, 6) .makesContact() .attr(TrapAttr, BattlerTagType.INFESTATION), new AttackMove(Moves.POWER_UP_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 20, 100, 0, 6) @@ -7191,11 +7299,11 @@ export function initMoves() { new AttackMove(Moves.OBLIVION_WING, Type.FLYING, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 6) .attr(HitHealAttr, 0.75) .triageMove(), - new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, 100, 0, 6) + new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) .attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(HitsTagAttr, BattlerTagType.FLYING, false) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) - .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING]) + .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN]) .makesContact(false) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) @@ -7214,9 +7322,9 @@ export function initMoves() { new AttackMove(Moves.PRECIPICE_BLADES, Type.GROUND, MoveCategory.PHYSICAL, 120, 85, 10, -1, 0, 6) .makesContact(false) .target(MoveTarget.ALL_NEAR_ENEMIES), - new AttackMove(Moves.DRAGON_ASCENT, Type.FLYING, MoveCategory.PHYSICAL, 120, 100, 5, 100, 0, 6) + new AttackMove(Moves.DRAGON_ASCENT, Type.FLYING, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 6) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], -1, true), - new AttackMove(Moves.HYPERSPACE_FURY, Type.DARK, MoveCategory.PHYSICAL, 100, -1, 5, 100, 0, 6) + new AttackMove(Moves.HYPERSPACE_FURY, Type.DARK, MoveCategory.PHYSICAL, 100, -1, 5, -1, 0, 6) .attr(StatChangeAttr, BattleStat.DEF, -1, true) .makesContact(false) .ignoresProtect(), @@ -7340,23 +7448,23 @@ export function initMoves() { .condition(new FirstMoveCondition()), new SelfStatusMove(Moves.BANEFUL_BUNKER, Type.POISON, -1, 10, -1, 4, 7) .attr(ProtectAttr, BattlerTagType.BANEFUL_BUNKER), - new AttackMove(Moves.SPIRIT_SHACKLE, Type.GHOST, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 7) + new AttackMove(Moves.SPIRIT_SHACKLE, Type.GHOST, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 7) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1) .makesContact(false), new AttackMove(Moves.DARKEST_LARIAT, Type.DARK, MoveCategory.PHYSICAL, 85, 100, 10, -1, 0, 7) .attr(IgnoreOpponentStatChangesAttr), - new AttackMove(Moves.SPARKLING_ARIA, Type.WATER, MoveCategory.SPECIAL, 90, 100, 10, -1, 0, 7) + new AttackMove(Moves.SPARKLING_ARIA, Type.WATER, MoveCategory.SPECIAL, 90, 100, 10, 100, 0, 7) .attr(HealStatusEffectAttr, false, StatusEffect.BURN) .soundBased() .target(MoveTarget.ALL_NEAR_OTHERS), - new AttackMove(Moves.ICE_HAMMER, Type.ICE, MoveCategory.PHYSICAL, 100, 90, 10, 100, 0, 7) + new AttackMove(Moves.ICE_HAMMER, Type.ICE, MoveCategory.PHYSICAL, 100, 90, 10, -1, 0, 7) .attr(StatChangeAttr, BattleStat.SPD, -1, true) .punchingMove(), new StatusMove(Moves.FLORAL_HEALING, Type.FAIRY, -1, 10, -1, 0, 7) .attr(BoostHealAttr, 0.5, 2/3, true, false, (user, target, move) => user.scene.arena.terrain?.terrainType === TerrainType.GRASSY) .triageMove(), new AttackMove(Moves.HIGH_HORSEPOWER, Type.GROUND, MoveCategory.PHYSICAL, 95, 95, 10, -1, 0, 7), - new StatusMove(Moves.STRENGTH_SAP, Type.GRASS, 100, 10, 100, 0, 7) + new StatusMove(Moves.STRENGTH_SAP, Type.GRASS, 100, 10, -1, 0, 7) .attr(HitHealAttr, null, Stat.ATK) .attr(StatChangeAttr, BattleStat.ATK, -1) .condition((user, target, move) => target.summonData.battleStats[BattleStat.ATK] > -6) @@ -7368,8 +7476,8 @@ export function initMoves() { new AttackMove(Moves.LEAFAGE, Type.GRASS, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 7) .makesContact(false), new StatusMove(Moves.SPOTLIGHT, Type.NORMAL, -1, 15, -1, 3, 7) - .unimplemented(), - new StatusMove(Moves.TOXIC_THREAD, Type.POISON, 100, 20, 100, 0, 7) + .attr(AddBattlerTagAttr, BattlerTagType.CENTER_OF_ATTENTION, false), + new StatusMove(Moves.TOXIC_THREAD, Type.POISON, 100, 20, -1, 0, 7) .attr(StatusEffectAttr, StatusEffect.POISON) .attr(StatChangeAttr, BattleStat.SPD, -1), new SelfStatusMove(Moves.LASER_FOCUS, Type.NORMAL, -1, 30, -1, 0, 7) @@ -7384,7 +7492,7 @@ export function initMoves() { .attr(StatusCategoryOnAllyAttr) .attr(HealOnAllyAttr, 0.5, true, false) .ballBombMove(), - new AttackMove(Moves.ANCHOR_SHOT, Type.STEEL, MoveCategory.PHYSICAL, 80, 100, 20, -1, 0, 7) + new AttackMove(Moves.ANCHOR_SHOT, Type.STEEL, MoveCategory.PHYSICAL, 80, 100, 20, 100, 0, 7) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1), new StatusMove(Moves.PSYCHIC_TERRAIN, Type.PSYCHIC, -1, 10, -1, 0, 7) .attr(TerrainChangeAttr, TerrainType.PSYCHIC) @@ -7428,7 +7536,7 @@ export function initMoves() { .ballBombMove() .makesContact(false) .partial(), - new AttackMove(Moves.CLANGING_SCALES, Type.DRAGON, MoveCategory.SPECIAL, 110, 100, 5, 100, 0, 7) + new AttackMove(Moves.CLANGING_SCALES, Type.DRAGON, MoveCategory.SPECIAL, 110, 100, 5, -1, 0, 7) .attr(StatChangeAttr, BattleStat.DEF, -1, true) .soundBased() .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -7462,17 +7570,17 @@ export function initMoves() { new AttackMove(Moves.PULVERIZING_PANCAKE, Type.NORMAL, MoveCategory.PHYSICAL, 210, -1, 1, -1, 0, 7) .partial() .ignoresVirtual(), - new SelfStatusMove(Moves.EXTREME_EVOBOOST, Type.NORMAL, -1, 1, 100, 0, 7) + new SelfStatusMove(Moves.EXTREME_EVOBOOST, Type.NORMAL, -1, 1, -1, 0, 7) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true) .ignoresVirtual(), - new AttackMove(Moves.GENESIS_SUPERNOVA, Type.PSYCHIC, MoveCategory.SPECIAL, 185, -1, 1, -1, 0, 7) + new AttackMove(Moves.GENESIS_SUPERNOVA, Type.PSYCHIC, MoveCategory.SPECIAL, 185, -1, 1, 100, 0, 7) .attr(TerrainChangeAttr, TerrainType.PSYCHIC) .ignoresVirtual(), /* End Unused */ new AttackMove(Moves.SHELL_TRAP, Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, -3, 7) .target(MoveTarget.ALL_NEAR_ENEMIES) .partial(), - new AttackMove(Moves.FLEUR_CANNON, Type.FAIRY, MoveCategory.SPECIAL, 130, 90, 5, 100, 0, 7) + new AttackMove(Moves.FLEUR_CANNON, Type.FAIRY, MoveCategory.SPECIAL, 130, 90, 5, -1, 0, 7) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new AttackMove(Moves.PSYCHIC_FANGS, Type.PSYCHIC, MoveCategory.PHYSICAL, 85, 100, 10, -1, 0, 7) .bitingMove() @@ -7495,7 +7603,7 @@ export function initMoves() { new AttackMove(Moves.MOONGEIST_BEAM, Type.GHOST, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7) .ignoresAbilities() .partial(), - new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, 100, 0, 7) + new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, -1, 0, 7) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -1), new AttackMove(Moves.ZING_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 30, 0, 7) .attr(FlinchAttr), @@ -7565,6 +7673,7 @@ export function initMoves() { new AttackMove(Moves.BADDY_BAD, Type.DARK, MoveCategory.SPECIAL, 80, 95, 15, -1, 0, 7) .attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, false, true), new AttackMove(Moves.SAPPY_SEED, Type.GRASS, MoveCategory.PHYSICAL, 100, 90, 10, 100, 0, 7) + .makesContact(false) .attr(AddBattlerTagAttr, BattlerTagType.SEEDED), new AttackMove(Moves.FREEZY_FROST, Type.ICE, MoveCategory.SPECIAL, 100, 90, 10, -1, 0, 7) .attr(ResetStatsAttr), @@ -7592,7 +7701,7 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, false, 1) .bitingMove(), - new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, 100, 0, 8) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki + new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, -1, 0, 8) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki .attr(EatBerryAttr) .attr(StatChangeAttr, BattleStat.DEF, 2, true) .condition((user) => { @@ -7600,10 +7709,10 @@ export function initMoves() { return userBerries.length > 0; }) .partial(), - new SelfStatusMove(Moves.NO_RETREAT, Type.FIGHTING, -1, 5, 100, 0, 8) + new SelfStatusMove(Moves.NO_RETREAT, Type.FIGHTING, -1, 5, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, true, 1), - new StatusMove(Moves.TAR_SHOT, Type.ROCK, 100, 15, 100, 0, 8) + new StatusMove(Moves.TAR_SHOT, Type.ROCK, 100, 15, -1, 0, 8) .attr(StatChangeAttr, BattleStat.SPD, -1) .partial(), new StatusMove(Moves.MAGIC_POWDER, Type.PSYCHIC, 100, 20, -1, 0, 8) @@ -7699,18 +7808,18 @@ export function initMoves() { .unimplemented() .ignoresVirtual(), /* End Unused */ - new SelfStatusMove(Moves.CLANGOROUS_SOUL, Type.DRAGON, 100, 5, 100, 0, 8) + new SelfStatusMove(Moves.CLANGOROUS_SOUL, Type.DRAGON, 100, 5, -1, 0, 8) .attr(CutHpStatBoostAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, 3) .soundBased() .danceMove(), new AttackMove(Moves.BODY_PRESS, Type.FIGHTING, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8) .attr(DefAtkAttr), - new StatusMove(Moves.DECORATE, Type.FAIRY, -1, 15, 100, 0, 8) + new StatusMove(Moves.DECORATE, Type.FAIRY, -1, 15, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 2), new AttackMove(Moves.DRUM_BEATING, Type.GRASS, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 8) .attr(StatChangeAttr, BattleStat.SPD, -1) .makesContact(false), - new AttackMove(Moves.SNAP_TRAP, Type.GRASS, MoveCategory.PHYSICAL, 35, 100, 15, 100, 0, 8) + new AttackMove(Moves.SNAP_TRAP, Type.GRASS, MoveCategory.PHYSICAL, 35, 100, 15, -1, 0, 8) .attr(TrapAttr, BattlerTagType.SNAP_TRAP), new AttackMove(Moves.PYRO_BALL, Type.FIRE, MoveCategory.PHYSICAL, 120, 90, 5, 10, 0, 8) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) @@ -7762,7 +7871,7 @@ export function initMoves() { new AttackMove(Moves.STEEL_ROLLER, Type.STEEL, MoveCategory.PHYSICAL, 130, 100, 5, -1, 0, 8) .attr(ClearTerrainAttr) .condition((user, target, move) => !!user.scene.arena.terrain), - new AttackMove(Moves.SCALE_SHOT, Type.DRAGON, MoveCategory.PHYSICAL, 25, 90, 20, 100, 0, 8) + new AttackMove(Moves.SCALE_SHOT, Type.DRAGON, MoveCategory.PHYSICAL, 25, 90, 20, -1, 0, 8) //.attr(StatChangeAttr, BattleStat.SPD, 1, true) // TODO: Have boosts only apply at end of move, not after every hit //.attr(StatChangeAttr, BattleStat.DEF, -1, true) .attr(MultiHitAttr) @@ -7802,7 +7911,7 @@ export function initMoves() { new StatusMove(Moves.CORROSIVE_GAS, Type.POISON, 100, 40, -1, 0, 8) .target(MoveTarget.ALL_NEAR_OTHERS) .unimplemented(), - new StatusMove(Moves.COACHING, Type.FIGHTING, -1, 10, 100, 0, 8) + new StatusMove(Moves.COACHING, Type.FIGHTING, -1, 10, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF ], 1) .target(MoveTarget.NEAR_ALLY), new AttackMove(Moves.FLIP_TURN, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 20, -1, 0, 8) @@ -7828,7 +7937,7 @@ export function initMoves() { .attr(MultiHitAttr, MultiHitType._3) .attr(CritOnlyAttr) .punchingMove(), - new AttackMove(Moves.THUNDER_CAGE, Type.ELECTRIC, MoveCategory.SPECIAL, 80, 90, 15, 100, 0, 8) + new AttackMove(Moves.THUNDER_CAGE, Type.ELECTRIC, MoveCategory.SPECIAL, 80, 90, 15, -1, 0, 8) .attr(TrapAttr, BattlerTagType.THUNDER_CAGE), new AttackMove(Moves.DRAGON_ENERGY, Type.DRAGON, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 8) .attr(HpPowerAttr) @@ -7846,16 +7955,16 @@ export function initMoves() { new AttackMove(Moves.ASTRAL_BARRAGE, Type.GHOST, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 8) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.EERIE_SPELL, Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 5, 100, 0, 8) - .soundBased() - .partial(), + .attr(AttackReducePpMoveAttr, 3) + .soundBased(), new AttackMove(Moves.DIRE_CLAW, Type.POISON, MoveCategory.PHYSICAL, 80, 100, 15, 50, 0, 8) .attr(MultiStatusEffectAttr, [StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP]), new AttackMove(Moves.PSYSHIELD_BASH, Type.PSYCHIC, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8) .attr(StatChangeAttr, BattleStat.DEF, 1, true), - new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, 100, 0, 8) + new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, -1, 0, 8) .unimplemented(), new AttackMove(Moves.STONE_AXE, Type.ROCK, MoveCategory.PHYSICAL, 65, 90, 15, 100, 0, 8) - .attr(AddArenaTrapTagAttr, ArenaTagType.STEALTH_ROCK) + .attr(AddArenaTrapTagHitAttr, ArenaTagType.STEALTH_ROCK) .slicingMove(), new AttackMove(Moves.SPRINGTIDE_STORM, Type.FAIRY, MoveCategory.SPECIAL, 100, 80, 5, 30, 0, 8) .attr(StatChangeAttr, BattleStat.ATK, -1) @@ -7874,10 +7983,10 @@ export function initMoves() { .attr(RecoilAttr, true, 0.5), new AttackMove(Moves.MOUNTAIN_GALE, Type.ICE, MoveCategory.PHYSICAL, 100, 85, 10, 30, 0, 8) .attr(FlinchAttr), - new SelfStatusMove(Moves.VICTORY_DANCE, Type.FIGHTING, -1, 10, 100, 0, 8) + new SelfStatusMove(Moves.VICTORY_DANCE, Type.FIGHTING, -1, 10, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPD ], 1, true) .danceMove(), - new AttackMove(Moves.HEADLONG_RUSH, Type.GROUND, MoveCategory.PHYSICAL, 120, 100, 5, 100, 0, 8) + new AttackMove(Moves.HEADLONG_RUSH, Type.GROUND, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], -1, true) .punchingMove(), new AttackMove(Moves.BARB_BARRAGE, Type.POISON, MoveCategory.PHYSICAL, 60, 100, 10, 50, 0, 8) @@ -7899,7 +8008,7 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.BURN) .attr(MovePowerMultiplierAttr, (user, target, move) => target.status ? 2 : 1), new AttackMove(Moves.CEASELESS_EDGE, Type.DARK, MoveCategory.PHYSICAL, 65, 90, 15, 100, 0, 8) - .attr(AddArenaTrapTagAttr, ArenaTagType.SPIKES) + .attr(AddArenaTrapTagHitAttr, ArenaTagType.SPIKES) .slicingMove(), new AttackMove(Moves.BLEAKWIND_STORM, Type.FLYING, MoveCategory.SPECIAL, 100, 80, 10, 30, 0, 8) .attr(ThunderAccuracyAttr) @@ -8040,15 +8149,15 @@ export function initMoves() { .makesContact(false), new AttackMove(Moves.LUMINA_CRASH, Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, 100, 0, 9) .attr(StatChangeAttr, BattleStat.SPDEF, -2), - new AttackMove(Moves.ORDER_UP, Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 9) + new AttackMove(Moves.ORDER_UP, Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 9) .makesContact(false) .partial(), new AttackMove(Moves.JET_PUNCH, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 15, -1, 1, 9) .punchingMove(), - new StatusMove(Moves.SPICY_EXTRACT, Type.GRASS, -1, 15, 100, 0, 9) + new StatusMove(Moves.SPICY_EXTRACT, Type.GRASS, -1, 15, -1, 0, 9) .attr(StatChangeAttr, BattleStat.ATK, 2) .attr(StatChangeAttr, BattleStat.DEF, -2), - new AttackMove(Moves.SPIN_OUT, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, 100, 0, 9) + new AttackMove(Moves.SPIN_OUT, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9) .attr(StatChangeAttr, BattleStat.SPD, -2, true), new AttackMove(Moves.POPULATION_BOMB, Type.NORMAL, MoveCategory.PHYSICAL, 20, 90, 10, -1, 0, 9) .attr(MultiHitAttr, MultiHitType._10) @@ -8062,7 +8171,7 @@ export function initMoves() { .triageMove() .attr(RevivalBlessingAttr) .target(MoveTarget.USER), - new AttackMove(Moves.SALT_CURE, Type.ROCK, MoveCategory.PHYSICAL, 40, 100, 15, -1, 0, 9) + new AttackMove(Moves.SALT_CURE, Type.ROCK, MoveCategory.PHYSICAL, 40, 100, 15, 100, 0, 9) .attr(AddBattlerTagAttr, BattlerTagType.SALT_CURED) .makesContact(false), new AttackMove(Moves.TRIPLE_DIVE, Type.WATER, MoveCategory.PHYSICAL, 30, 95, 10, -1, 0, 9) @@ -8125,7 +8234,7 @@ export function initMoves() { .attr(WeatherChangeAttr, WeatherType.SNOW) .attr(ForceSwitchOutAttr, true, false) .target(MoveTarget.BOTH_SIDES), - new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, 100, 0, 9) + new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, -1, 0, 9) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPD ], 1, true, null, true, true) .attr(RemoveArenaTrapAttr) .target(MoveTarget.BOTH_SIDES), @@ -8136,7 +8245,7 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPD, -1), new AttackMove(Moves.TRAILBLAZE, Type.GRASS, MoveCategory.PHYSICAL, 50, 100, 20, 100, 0, 9) .attr(StatChangeAttr, BattleStat.SPD, 1, true), - new AttackMove(Moves.CHILLING_WATER, Type.WATER, MoveCategory.SPECIAL, 50, 100, 20, -1, 0, 9) + new AttackMove(Moves.CHILLING_WATER, Type.WATER, MoveCategory.SPECIAL, 50, 100, 20, 100, 0, 9) .attr(StatChangeAttr, BattleStat.ATK, -1), new AttackMove(Moves.HYPER_DRILL, Type.NORMAL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9) .ignoresProtect(), @@ -8198,8 +8307,7 @@ export function initMoves() { .attr(HealStatusEffectAttr, false, StatusEffect.FREEZE) .attr(StatusEffectAttr, StatusEffect.BURN) .target(MoveTarget.ALL_NEAR_ENEMIES) - .triageMove() - .partial(), + .triageMove(), new AttackMove(Moves.SYRUP_BOMB, Type.GRASS, MoveCategory.SPECIAL, 60, 85, 10, -1, 0, 9) .attr(StatChangeAttr, BattleStat.SPD, -1) //Temporary .ballBombMove() @@ -8217,7 +8325,7 @@ export function initMoves() { new AttackMove(Moves.FICKLE_BEAM, Type.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9) .attr(PreMoveMessageAttr, doublePowerChanceMessageFunc) .attr(DoublePowerChanceAttr), - new SelfStatusMove(Moves.BURNING_BULWARK, Type.FIRE, -1, 10, 100, 4, 9) + new SelfStatusMove(Moves.BURNING_BULWARK, Type.FIRE, -1, 10, -1, 4, 9) .attr(ProtectAttr, BattlerTagType.BURNING_BULWARK), new AttackMove(Moves.THUNDERCLAP, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 5, -1, 1, 9) .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move].category !== MoveCategory.STATUS), @@ -8229,7 +8337,7 @@ export function initMoves() { .slicingMove(), new AttackMove(Moves.HARD_PRESS, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9) .attr(OpponentHighHpPowerAttr), - new StatusMove(Moves.DRAGON_CHEER, Type.DRAGON, -1, 15, 100, 0, 9) + new StatusMove(Moves.DRAGON_CHEER, Type.DRAGON, -1, 15, -1, 0, 9) .attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, false, true) .target(MoveTarget.NEAR_ALLY) .partial(), diff --git a/src/data/pokeball.ts b/src/data/pokeball.ts index de8d5456f45..0399e383820 100644 --- a/src/data/pokeball.ts +++ b/src/data/pokeball.ts @@ -1,5 +1,5 @@ import BattleScene from "../battle-scene"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; export enum PokeballType { POKEBALL, diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 58050c99d78..eddcf3c97b7 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -13,7 +13,8 @@ import { speciesEggMoves } from "./egg-moves"; import { GameMode } from "../game-mode"; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities"; import { VariantSet } from "./variant"; -import i18next, { Localizable } from "../plugins/i18n"; +import i18next from "i18next"; +import { Localizable } from "#app/interfaces/locales"; import { Stat } from "./pokemon-stat"; import { Abilities } from "#enums/abilities"; import { PartyMemberStrength } from "#enums/party-member-strength"; @@ -3795,7 +3796,7 @@ export const starterPassiveAbilities = { [Species.IRON_TREADS]: Abilities.STEELY_SPIRIT, [Species.IRON_BUNDLE]: Abilities.SNOW_WARNING, [Species.IRON_HANDS]: Abilities.IRON_FIST, - [Species.IRON_JUGULIS]: Abilities.AERILATE, + [Species.IRON_JUGULIS]: Abilities.LIGHTNING_ROD, [Species.IRON_MOTH]: Abilities.LEVITATE, [Species.IRON_THORNS]: Abilities.SAND_STREAM, [Species.FRIGIBAX]: Abilities.SNOW_WARNING, diff --git a/src/data/pokemon-stat.ts b/src/data/pokemon-stat.ts index c1faee0e177..a6bf77b1daa 100644 --- a/src/data/pokemon-stat.ts +++ b/src/data/pokemon-stat.ts @@ -1,4 +1,4 @@ -import i18next from "../plugins/i18n"; +import i18next from "i18next"; export enum Stat { HP = 0, diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index 1732d215ef5..bd64456c993 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -1,4 +1,4 @@ -import i18next from "../plugins/i18n"; +import i18next from "i18next"; export function getBattleCountSplashMessage(): string { return `{COUNT} ${i18next.t("splashMessages:battlesWon")}`; diff --git a/src/egg-hatch-phase.ts b/src/egg-hatch-phase.ts index 3fce35e4f88..6e44b832181 100644 --- a/src/egg-hatch-phase.ts +++ b/src/egg-hatch-phase.ts @@ -262,6 +262,9 @@ export class EggHatchPhase extends Phase { if (!this.canSkip || this.skipped) { return false; } + if (this.eggCounterContainer.eggCountText?.data === undefined) { + return false; + } this.skipped = true; if (!this.hatched) { this.doHatch(); diff --git a/src/enums/battler-tag-type.ts b/src/enums/battler-tag-type.ts index 98f01c9c375..4d212a2da12 100644 --- a/src/enums/battler-tag-type.ts +++ b/src/enums/battler-tag-type.ts @@ -58,5 +58,6 @@ export enum BattlerTagType { MAGNET_RISEN = "MAGNET_RISEN", MINIMIZED = "MINIMIZED", DESTINY_BOND = "DESTINY_BOND", + CENTER_OF_ATTENTION = "CENTER_OF_ATTENTION", ICE_FACE = "ICE_FACE" } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index b06eab043ba..57a472585d5 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -18,11 +18,11 @@ import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEv import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms"; import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase, ToggleDoublePositionPhase } from "../phases"; import { BattleStat } from "../data/battle-stat"; -import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from "../data/battler-tags"; +import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, TypeImmuneTag, getBattlerTag } from "../data/battler-tags"; import { WeatherType } from "../data/weather"; import { TempBattleStat } from "../data/temp-battle-stat"; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from "../data/arena-tag"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr } from "../data/ability"; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AllyMoveCategoryPowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr } from "../data/ability"; import PokemonData from "../system/pokemon-data"; import { BattlerIndex } from "../battle"; import { Mode } from "../ui/ui"; @@ -37,7 +37,7 @@ import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMov import { TerrainType } from "../data/terrain"; import { TrainerSlot } from "../data/trainer-config"; import * as Overrides from "../overrides"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { speciesEggMoves } from "../data/egg-moves"; import { ModifierTier } from "../modifier/modifier-tier"; import { applyChallenges, ChallengeType } from "#app/data/challenge.js"; @@ -1096,7 +1096,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } isGrounded(): boolean { - return !this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE); + return !this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN); } /** @@ -1134,6 +1134,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!cancelled.value && !ignoreAbility) { applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true); } + return (!cancelled.value ? typeMultiplier.value : 0) as TypeDamageMultiplier; } @@ -1161,6 +1162,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!ignoreStrongWinds && this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && multiplier >= 2 && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) { multiplier /= 2; } + + if (!!this.summonData?.tags.find((tag) => tag instanceof TypeImmuneTag && tag.immuneType === moveType)) { + multiplier = 0; + } + return multiplier; } @@ -1724,7 +1730,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (typeless) { typeMultiplier.value = 1; } - if (types.find(t => move.isTypeImmune(t))) { + if (types.find(t => move.isTypeImmune(source, this, t))) { typeMultiplier.value = 0; } @@ -1747,7 +1753,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { power.value = 60; } applyPreAttackAbAttrs(VariableMovePowerAbAttr, source, this, move, power); - this.scene.getField(true).map(p => applyPreAttackAbAttrs(FieldVariableMovePowerAbAttr, this, source, move, power)); + + if (source.getAlly()?.hasAbilityWithAttr(AllyMoveCategoryPowerBoostAbAttr)) { + applyPreAttackAbAttrs(AllyMoveCategoryPowerBoostAbAttr, source, this, move, power); + } + + const fieldAuras = new Set( + this.scene.getField(true) + .map((p) => p.getAbilityAttrs(FieldMoveTypePowerBoostAbAttr) as FieldMoveTypePowerBoostAbAttr[]) + .flat(), + ); + for (const aura of fieldAuras) { + // The only relevant values are `move` and the `power` holder + aura.applyPreAttack(null, null, null, move, [power]); + } applyPreDefendAbAttrs(ReceivedMoveDamageMultiplierAbAttr, this, source, move, cancelled, power); diff --git a/src/interfaces/locales.ts b/src/interfaces/locales.ts new file mode 100644 index 00000000000..21fbda7c468 --- /dev/null +++ b/src/interfaces/locales.ts @@ -0,0 +1,76 @@ +export interface Localizable { + localize(): void; + } + +export interface SimpleTranslationEntries { + [key: string]: string + } + +export interface MoveTranslationEntry { + name: string, + effect: string + } + +export interface MoveTranslationEntries { + [key: string]: MoveTranslationEntry + } + +export interface AbilityTranslationEntry { + name: string, + description: string + } + +export interface AbilityTranslationEntries { + [key: string]: AbilityTranslationEntry + } + +export interface ModifierTypeTranslationEntry { + name?: string, + description?: string, + extra?: SimpleTranslationEntries + } + +export interface ModifierTypeTranslationEntries { + ModifierType: { [key: string]: ModifierTypeTranslationEntry }, + AttackTypeBoosterItem: SimpleTranslationEntries, + TempBattleStatBoosterItem: SimpleTranslationEntries, + TempBattleStatBoosterStatName: SimpleTranslationEntries, + BaseStatBoosterItem: SimpleTranslationEntries, + EvolutionItem: SimpleTranslationEntries, + FormChangeItem: SimpleTranslationEntries, + } + +export interface PokemonInfoTranslationEntries { + Stat: SimpleTranslationEntries, + Type: SimpleTranslationEntries, + } + +export interface BerryTranslationEntry { + name: string, + effect: string, + } + +export interface BerryTranslationEntries { + [key: string]: BerryTranslationEntry + } + +export interface AchievementTranslationEntry { + name?: string, + description?: string, + } + +export interface AchievementTranslationEntries { + [key: string]: AchievementTranslationEntry; + } + +export interface DialogueTranslationEntry { + [key: number]: string; + } + +export interface DialogueTranslationCategory { + [category: string]: DialogueTranslationEntry; + } + +export interface DialogueTranslationEntries { + [trainertype: string]: DialogueTranslationCategory; + } diff --git a/src/loading-scene.ts b/src/loading-scene.ts index fbe1d23f049..f6ca88192da 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -24,6 +24,8 @@ import { Biome } from "#enums/biome"; import { TrainerType } from "#enums/trainer-type"; export class LoadingScene extends SceneBase { + readonly LOAD_EVENTS = Phaser.Loader.Events; + constructor() { super("loading"); @@ -35,10 +37,6 @@ export class LoadingScene extends SceneBase { Utils.localPing(); this.load["manifest"] = this.game["manifest"]; - if (!isMobile()) { - this.load.video("intro_dark", "images/intro_dark.mp4", true); - } - this.loadImage("loading_bg", "arenas"); this.loadImage("logo", ""); this.loadImage("pride-update", "events"); @@ -421,58 +419,46 @@ export class LoadingScene extends SceneBase { }); disclaimerDescriptionText.setOrigin(0.5, 0.5); - disclaimerText.setVisible(false); - disclaimerDescriptionText.setVisible(false); - - const intro = this.add.video(0, 0); - intro.setOrigin(0, 0); - intro.setScale(3); - - this.load.on("progress", (value: string) => { - const parsedValue = parseFloat(value); - percentText.setText(`${Math.floor(parsedValue * 100)}%`); - progressBar.clear(); - progressBar.fillStyle(0xffffff, 0.8); - progressBar.fillRect(midWidth - 320, 360, 640 * parsedValue, 64); - }); - - this.load.on("fileprogress", file => { - assetText.setText(i18next.t("menu:loadingAsset", { assetName: file.key })); - }); - - loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText); + loadingGraphics.push(bg, graphics, progressBar, progressBox, logo, percentText, assetText, disclaimerText, disclaimerDescriptionText); if (!mobile) { loadingGraphics.map(g => g.setVisible(false)); } - const destroyLoadingAssets = () => { - intro.destroy(); - bg.destroy(); - logo.destroy(); - progressBar.destroy(); - progressBox.destroy(); - percentText.destroy(); - assetText.destroy(); - }; + const intro = this.add.video(0, 0); + intro.on(Phaser.GameObjects.Events.VIDEO_COMPLETE, (video: Phaser.GameObjects.Video) => { + this.tweens.add({ + targets: intro, + duration: 500, + alpha: 0, + ease: "Sine.easeIn", + onComplete: () => video.destroy(), + }); + loadingGraphics.forEach(g => g.setVisible(true)); + }); + intro.setOrigin(0, 0); + intro.setScale(3); - this.load.on("filecomplete", key => { + this.load.once(this.LOAD_EVENTS.START, () => { + // videos do not need to be preloaded + intro.loadURL("images/intro_dark.mp4", true); + if (mobile) { + intro.video.setAttribute("webkit-playsinline", "webkit-playsinline"); + intro.video.setAttribute("playsinline", "playsinline"); + } + intro.play(); + }); + + this.load.on(this.LOAD_EVENTS.PROGRESS , (progress: number) => { + percentText.setText(`${Math.floor(progress * 100)}%`); + progressBar.clear(); + progressBar.fillStyle(0xffffff, 0.8); + progressBar.fillRect(midWidth - 320, 360, 640 * progress, 64); + }); + + this.load.on(this.LOAD_EVENTS.FILE_COMPLETE, (key: string) => { + assetText.setText(i18next.t("menu:loadingAsset", { assetName: key })); switch (key) { - case "intro_dark": - intro.load("intro_dark"); - intro.on("complete", () => { - this.tweens.add({ - targets: intro, - duration: 500, - alpha: 0, - ease: "Sine.easeIn" - }); - loadingGraphics.map(g => g.setVisible(true)); - disclaimerText.setVisible(true); - disclaimerDescriptionText.setVisible(true); - }); - intro.play(); - break; case "loading_bg": bg.setTexture("loading_bg"); if (mobile) { @@ -488,7 +474,7 @@ export class LoadingScene extends SceneBase { } }); - this.load.on("complete", () => destroyLoadingAssets()); + this.load.on(this.LOAD_EVENTS.COMPLETE, () => loadingGraphics.forEach(go => go.destroy())); } get gameHeight() { diff --git a/src/locales/de/ability-trigger.ts b/src/locales/de/ability-trigger.ts index 652c16eb662..895f2f55c64 100644 --- a/src/locales/de/ability-trigger.ts +++ b/src/locales/de/ability-trigger.ts @@ -1,8 +1,8 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!", "badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!", "windPowerCharged": "Der Treffer durch {{moveName}} läd die Stärke von {{pokemonName}} auf!", - "iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!", + "iceFaceAvoidedDamage": "{{pokemonName}} wehrt Schaden\nmit {{abilityName}} ab!", } as const; diff --git a/src/locales/de/ability.ts b/src/locales/de/ability.ts index 4567976e0ef..e397b84c7b7 100644 --- a/src/locales/de/ability.ts +++ b/src/locales/de/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { stench: { diff --git a/src/locales/de/achv.ts b/src/locales/de/achv.ts index 64721e48af6..6040c3ea916 100644 --- a/src/locales/de/achv.ts +++ b/src/locales/de/achv.ts @@ -1,4 +1,4 @@ -import {AchievementTranslationEntries} from "#app/plugins/i18n.js"; +import {AchievementTranslationEntries} from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/de/battle-message-ui-handler.ts b/src/locales/de/battle-message-ui-handler.ts index daedb8550d0..cc1deccbaa2 100644 --- a/src/locales/de/battle-message-ui-handler.ts +++ b/src/locales/de/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "Sensationell", diff --git a/src/locales/de/battle.ts b/src/locales/de/battle.ts index 86336b0e233..09310ca02bc 100644 --- a/src/locales/de/battle.ts +++ b/src/locales/de/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} erscheint.", @@ -62,12 +62,13 @@ export const battle: SimpleTranslationEntries = { "drainMessage": "{{pokemonName}} wurde Energie abgesaugt", "regainHealth": "KP von {{pokemonName}} wurden wieder aufgefrischt!", "fainted": "{{pokemonNameWithAffix}} wurde besiegt!", - "statRose": "rose", - "statSharplyRose": "sharply rose", - "statRoseDrastically": "rose drastically", - "statWontGoAnyHigher": "won't go any higher", - "statFell": "fell", - "statHarshlyFell": "harshly fell", - "statSeverelyFell": "severely fell", - "statWontGoAnyLower": "won't go any lower", + "statRose": "steigt", + "statSharplyRose": "steigt stark", + "statRoseDrastically": "steigt drastisch", + "statWontGoAnyHigher": "kann nicht weiter erhöht werden", + "statFell": "sinkt", + "statHarshlyFell": "sinkt stark", + "statSeverelyFell": "sinkt drastisch", + "statWontGoAnyLower": "kann nicht weiter sinken", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/de/berry.ts b/src/locales/de/berry.ts index 093c3f708eb..b041a23d646 100644 --- a/src/locales/de/berry.ts +++ b/src/locales/de/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/de/biome.ts b/src/locales/de/biome.ts index 6fdbb3c6820..2afb4a4b018 100644 --- a/src/locales/de/biome.ts +++ b/src/locales/de/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "An einem unbekannten Ort", diff --git a/src/locales/de/challenges.ts b/src/locales/de/challenges.ts index 1dbd4505986..b3e878f4649 100644 --- a/src/locales/de/challenges.ts +++ b/src/locales/de/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "Herausforderungsmodifikatoren", diff --git a/src/locales/de/command-ui-handler.ts b/src/locales/de/command-ui-handler.ts index fcc70e5d59d..cd7da3fbf26 100644 --- a/src/locales/de/command-ui-handler.ts +++ b/src/locales/de/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "Kampf", diff --git a/src/locales/de/config.ts b/src/locales/de/config.ts index b02bd5aeee6..16c25d6ca78 100644 --- a/src/locales/de/config.ts +++ b/src/locales/de/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/de/settings.js"; export const deConfig = { ability: ability, @@ -74,6 +75,7 @@ export const deConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/de/dialogue.ts b/src/locales/de/dialogue.ts index 8ae8e7a5b03..02c497b3182 100644 --- a/src/locales/de/dialogue.ts +++ b/src/locales/de/dialogue.ts @@ -1,4 +1,4 @@ -import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins/i18n"; +import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) @@ -2351,31 +2351,30 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "alder": { "encounter": { - 1: "Prepare yourself for a match against the strongest Trainer in Unova!" + 1: "Mach dich bereit für einen Kampf gegen den stärksten Trainer in Einall! Mich - Lauro!" }, "victory": { - 1: "Well done! You certainly are an unmatched talent." + 1: "Gut gemacht! Du hast wirklich ein unvergleichliches Talent." }, "defeat": { - 1: `A fresh wind blows through my heart... - $What an extraordinary effort!` + 1: `Ein frischer Wind weht durch mein Herz... + $Was für ein außergewöhnliches Gefühl!` } }, "kieran": { "encounter": { - 1: `Through hard work, I become stronger and stronger! - $I don't lose.` + 1: `Durch harte Arbeit werde ich immer stärker und stärker! + $Ich verliere nicht.` }, "victory": { - 1: `I don't believe it... - $What a fun and heart-pounding battle!` + 1: `Ich kann es nicht glauben... + $Was für ein lustiger und herzzerreißender Kampf!` }, "defeat": { - 1: `Wowzers, what a battle! - $Time for you to train even harder.` + 1: `Wow, was für ein Kampf! + $Es ist Zeit für dich, noch härter zu trainieren.` } }, - "rival": { "encounter": { 1: `@c{smile}Hey, ich habe dich gesucht! Ich weiß, dass du es nicht erwarten konntest loszugehen, diff --git a/src/locales/de/egg.ts b/src/locales/de/egg.ts index b55c3a229d0..e4a66f9ba87 100644 --- a/src/locales/de/egg.ts +++ b/src/locales/de/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "Ei", diff --git a/src/locales/de/fight-ui-handler.ts b/src/locales/de/fight-ui-handler.ts index 4c6ec243a22..255b48b3aa4 100644 --- a/src/locales/de/fight-ui-handler.ts +++ b/src/locales/de/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "AP", diff --git a/src/locales/de/game-mode.ts b/src/locales/de/game-mode.ts index 59058a6ab49..72661bd4682 100644 --- a/src/locales/de/game-mode.ts +++ b/src/locales/de/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "Klassik", diff --git a/src/locales/de/game-stats-ui-handler.ts b/src/locales/de/game-stats-ui-handler.ts index 8c582b33eb1..776a28f95c7 100644 --- a/src/locales/de/game-stats-ui-handler.ts +++ b/src/locales/de/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "Statistiken", diff --git a/src/locales/de/growth.ts b/src/locales/de/growth.ts index dbd0e119e5f..275f1645b87 100644 --- a/src/locales/de/growth.ts +++ b/src/locales/de/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "Unregelmäßig", diff --git a/src/locales/de/menu-ui-handler.ts b/src/locales/de/menu-ui-handler.ts index de30785b731..62c53be4c62 100644 --- a/src/locales/de/menu-ui-handler.ts +++ b/src/locales/de/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "Spieleinstellungen", diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index d8987fcf77b..beb46ff16aa 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,8 +34,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "Sitzung erfolgreich geladen.", "failedToLoadSession": "Ihre Sitzungsdaten konnten nicht geladen werden.\nSie könnten beschädigt sein.", "boyOrGirl": "Bist du ein Junge oder ein Mädchen?", - "boy": "Junge", - "girl": "Mädchen", "evolving": "Nanu?\n{{pokemonName}} entwickelt sich!", "stoppedEvolving": "Hm? {{pokemonName}} hat die Entwicklung \nabgebrochen.", // "Hm? Entwicklung wurde abgebrochen!" without naming the pokemon seems to be the original. "pauseEvolutionsQuestion": "Die Entwicklung von {{pokemonName}} vorübergehend pausieren?\nEntwicklungen können im Gruppenmenü wieder aktiviert werden.", @@ -44,11 +42,15 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "Tägliche Rangliste", "weeklyRankings": "Wöchentliche Rangliste", "noRankings": "Keine Rangliste", + "positionIcon": "#", + "usernameScoreboard": "Benutzername", + "score": "Punkte", + "wave": "Welle", "loading": "Lade…", "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "Spieler Online", "yes":"Ja", "no":"Nein", "disclaimer": "DISCLAIMER", - "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed." + "disclaimerDescription": "Dieses Spiel ist ein unfertiges Produkt. Es kann spielbeinträchtigende Fehler (bis hin zum Verlust des Speicherstandes)\n aufweisen, sich ohne Vorankündigung ändern und es gibt keine Garantie dass es weiterentwickelt oder fertiggestellt wird.", } as const; diff --git a/src/locales/de/modifier-type.ts b/src/locales/de/modifier-type.ts index 8f0f7aded5c..f5536e2c6d7 100644 --- a/src/locales/de/modifier-type.ts +++ b/src/locales/de/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/de/move.ts b/src/locales/de/move.ts index 8af2e8bb022..430b4f85ec3 100644 --- a/src/locales/de/move.ts +++ b/src/locales/de/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { "pound": { diff --git a/src/locales/de/nature.ts b/src/locales/de/nature.ts index 3b730dd0455..0156b8515df 100644 --- a/src/locales/de/nature.ts +++ b/src/locales/de/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "Robust", diff --git a/src/locales/de/party-ui-handler.ts b/src/locales/de/party-ui-handler.ts index 103c6837889..da83d2370c3 100644 --- a/src/locales/de/party-ui-handler.ts +++ b/src/locales/de/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "SEND_OUT": "Einwechseln", diff --git a/src/locales/de/pokeball.ts b/src/locales/de/pokeball.ts index 0b850b5c775..395134be844 100644 --- a/src/locales/de/pokeball.ts +++ b/src/locales/de/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "Pokéball", diff --git a/src/locales/de/pokemon-info-container.ts b/src/locales/de/pokemon-info-container.ts index 41cca2d7dbb..f408dbcff9c 100644 --- a/src/locales/de/pokemon-info-container.ts +++ b/src/locales/de/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "Attacken", diff --git a/src/locales/de/pokemon-info.ts b/src/locales/de/pokemon-info.ts index 0d350a75c36..08a23de2b3a 100644 --- a/src/locales/de/pokemon-info.ts +++ b/src/locales/de/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { @@ -14,8 +14,8 @@ export const pokemonInfo: PokemonInfoTranslationEntries = { "SPDEFshortened": "SpVert", "SPD": "Initiative", "SPDshortened": "Init", - "ACC": "Accuracy", - "EVA": "Evasiveness" + "ACC": "Genauigkeit", + "EVA": "Fluchtwert", }, Type: { diff --git a/src/locales/de/pokemon.ts b/src/locales/de/pokemon.ts index bd2ff964a9b..58a0439f5d5 100644 --- a/src/locales/de/pokemon.ts +++ b/src/locales/de/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "Bisasam", diff --git a/src/locales/de/save-slot-select-ui-handler.ts b/src/locales/de/save-slot-select-ui-handler.ts index fbbfebae6ee..b6577cd574a 100644 --- a/src/locales/de/save-slot-select-ui-handler.ts +++ b/src/locales/de/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "Den ausgewählten Speicherstand überschreiben?", diff --git a/src/locales/de/settings.ts b/src/locales/de/settings.ts new file mode 100644 index 00000000000..ba040e91810 --- /dev/null +++ b/src/locales/de/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "Junge", + "girl": "Mädchen", + "general": "Allgemein", + "display": "Anzeige", + "audio": "Audio", + "gamepad": "Controller", + "keyboard": "Tastatur", + "gameSpeed": "Spielgeschwindigkeit", + "hpBarSpeed": "KP-Balken Geschwindigkeit", + "expGainsSpeed": "EXP-Balken Geschwindigkeit", + "expPartyDisplay": "Team-EXP anzeigen", + "skipSeenDialogues": "Gesehenen Dialog überspringen", + "battleStyle": "Kampfstil", + "enableRetries": "Erneut versuchen aktivieren", + "tutorials": "Tutorials", + "touchControls": "Touch Steuerung", + "vibrations": "Vibration", + "normal": "Normal", + "fast": "Schnell", + "faster": "Schneller", + "skip": "Überspringen", + "levelUpNotifications": "Auflevelbenachrichtigung", + "on": "An", + "off": "Aus", + "switch": "Wechsel", + "set": "Folge", + "auto": "Auto", + "disabled": "Deaktiviert", + "language": "Sprache", + "change": "Ändern", + "uiTheme": "UI Thema", + "default": "Standard", + "legacy": "Legacy", + "windowType": "Fenster Typ", + "moneyFormat": "Währungsformat", + "damageNumbers": "Schadensnummern", + "simple": "Simpel", + "fancy": "Schön", + "abbreviated": "Abgekürzt", + "moveAnimations": "Attacken Animationen", + "showStatsOnLevelUp": "Werte beim Aufleveln anzeigen", + "candyUpgradeNotification": "Bonbon Upgrade Benachrichtigung", + "passivesOnly": "Nur Passive", + "candyUpgradeDisplay": "Bonbon Upgrade Anzeige", + "icon": "Icon", + "animation": "Animation", + "moveInfo": "Attacken-Info", + "showMovesetFlyout": "Zeige Attacken Flyout", + "showArenaFlyout": "Zeige Arena Flyout", + "showTimeOfDayWidget": "Zeige Tageszeit Widget", + "timeOfDayAnimation": "Tageszeit Animation", + "bounce": "Springen", + "timeOfDay_back": "Zurück", + "spriteSet": "Sprite Satz", + "consistent": "Konistent", + "mixedAnimated": "Gemischt animiert", + "fusionPaletteSwaps": "Fusion-Farbpalettenwechsel", + "playerGender": "Spieler Geschlecht", + "typeHints": "Typhinweise", + "masterVolume": "Gesamtlautstärke", + "bgmVolume": "Hintergrundmusik", + "seVolume": "Spezialeffekte", + "musicPreference": "Musik Präferenz", + "mixed": "Gemisch", + "gamepadPleasePlug": "Bitte einen Controller anschließen oder eine Taste drücken", + "delete": "Löschen", + "keyboardPleasePress": "Bitte eine Taste auf der Tastatur drücken", + "reset": "Zurücksetzen", + "requireReload": "Neuladen benötigt", + "action": "Aktion", + "back": "Zurück", + "pressToBind": "Zum Zuweisen drücken", + "pressButton": "Eine Taste drücken...", + "buttonUp": "Hoch", + "buttonDown": "Runter", + "buttonLeft": "Links", + "buttonRight": "Rechts", + "buttonAction": "Aktion", + "buttonMenu": "Menü", + "buttonSubmit": "Bestätigen", + "buttonCancel": "Abbrechen", + "buttonStats": "Statistiken", + "buttonCycleForm": "Form wechseln", + "buttonCycleShiny": "Schillernd wechseln", + "buttonCycleGender": "Geschlecht wechseln", + "buttonCycleAbility": "Fähigkeit wechseln", + "buttonCycleNature": "Wesen wechseln", + "buttonCycleVariant": "Variante wechseln", + "buttonSpeedUp": "Beschleunigen", + "buttonSlowDown": "Verlangsamen", + "alt": " (Alt)", + "mute": "Mute", + "controller": "Controller", + "gamepadSupport": "Gamepad Support" +} as const; diff --git a/src/locales/de/splash-messages.ts b/src/locales/de/splash-messages.ts index fda502120e0..f5ab8572b7b 100644 --- a/src/locales/de/splash-messages.ts +++ b/src/locales/de/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "Kämpfe gewonnen!", diff --git a/src/locales/de/starter-select-ui-handler.ts b/src/locales/de/starter-select-ui-handler.ts index a448dcedad8..c82f579c341 100644 --- a/src/locales/de/starter-select-ui-handler.ts +++ b/src/locales/de/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "addToParty": "Zum Team hinzufügen", "toggleIVs": "DVs anzeigen/verbergen", "manageMoves": "Attacken ändern", + "manageNature": "Wesen ändern", "useCandies": "Bonbons verwenden", + "selectNature": "Wähle das neue Wesen.", "selectMoveSwapOut": "Wähle die zu ersetzende Attacke.", "selectMoveSwapWith": "Wähle die gewünschte Attacke.", "unlockPassive": "Passiv-Skill freischalten", diff --git a/src/locales/de/trainers.ts b/src/locales/de/trainers.ts index b473bb94094..7be3c019903 100644 --- a/src/locales/de/trainers.ts +++ b/src/locales/de/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/de/tutorial.ts b/src/locales/de/tutorial.ts index 2f27cb10d61..0b02c6c0922 100644 --- a/src/locales/de/tutorial.ts +++ b/src/locales/de/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `Willkommen bei PokéRogue! Dies ist ein kampforientiertes Pokémon-Fangame mit Roguelite-Elementen. diff --git a/src/locales/de/voucher.ts b/src/locales/de/voucher.ts index 80e22931982..3ca01689875 100644 --- a/src/locales/de/voucher.ts +++ b/src/locales/de/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "Gutscheine", diff --git a/src/locales/de/weather.ts b/src/locales/de/weather.ts index ab1dde97639..1132c35c430 100644 --- a/src/locales/de/weather.ts +++ b/src/locales/de/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/en/ability-trigger.ts b/src/locales/en/ability-trigger.ts index 52f333f69a9..d22af7d8bb4 100644 --- a/src/locales/en/ability-trigger.ts +++ b/src/locales/en/ability-trigger.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!", diff --git a/src/locales/en/ability.ts b/src/locales/en/ability.ts index aff5d95405e..7e81f90afff 100644 --- a/src/locales/en/ability.ts +++ b/src/locales/en/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { stench: { diff --git a/src/locales/en/achv.ts b/src/locales/en/achv.ts index 571935aaddf..bff75344ea5 100644 --- a/src/locales/en/achv.ts +++ b/src/locales/en/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/en/battle-message-ui-handler.ts b/src/locales/en/battle-message-ui-handler.ts index 6f09770808f..c213c666a26 100644 --- a/src/locales/en/battle-message-ui-handler.ts +++ b/src/locales/en/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "Best", @@ -7,4 +7,4 @@ export const battleMessageUiHandler: SimpleTranslationEntries = { "ivPrettyGood": "Pretty Good", "ivDecent": "Decent", "ivNoGood": "No Good", -} as const; +} as const; diff --git a/src/locales/en/battle.ts b/src/locales/en/battle.ts index 39393331a72..e5afe934492 100644 --- a/src/locales/en/battle.ts +++ b/src/locales/en/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} appeared.", @@ -70,4 +70,5 @@ export const battle: SimpleTranslationEntries = { "statHarshlyFell": "harshly fell", "statSeverelyFell": "severely fell", "statWontGoAnyLower": "won't go any lower", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/en/berry.ts b/src/locales/en/berry.ts index 1063b84046d..3c4930b1591 100644 --- a/src/locales/en/berry.ts +++ b/src/locales/en/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/en/biome.ts b/src/locales/en/biome.ts index 5631b91b836..d3f34c021d4 100644 --- a/src/locales/en/biome.ts +++ b/src/locales/en/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "Somewhere you can\'t remember", diff --git a/src/locales/en/challenges.ts b/src/locales/en/challenges.ts index 7401104e1a3..746a7e962d2 100644 --- a/src/locales/en/challenges.ts +++ b/src/locales/en/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "Challenge Modifiers", diff --git a/src/locales/en/command-ui-handler.ts b/src/locales/en/command-ui-handler.ts index b5a87b72ffd..c4c65db0aa0 100644 --- a/src/locales/en/command-ui-handler.ts +++ b/src/locales/en/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "Fight", diff --git a/src/locales/en/config.ts b/src/locales/en/config.ts index b6a01c1b336..98b36ea61ab 100644 --- a/src/locales/en/config.ts +++ b/src/locales/en/config.ts @@ -1,3 +1,4 @@ +import { settings } from "#app/locales/en/settings.js"; import { ability } from "./ability"; import { abilityTriggers } from "./ability-trigger"; import { PGFachv, PGMachv } from "./achv"; @@ -75,6 +76,7 @@ export const enConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/en/dialogue.ts b/src/locales/en/dialogue.ts index 612cb780799..fb45d82765b 100644 --- a/src/locales/en/dialogue.ts +++ b/src/locales/en/dialogue.ts @@ -1,4 +1,4 @@ -import { DialogueTranslationEntries, SimpleTranslationEntries } from "#app/plugins/i18n"; +import { DialogueTranslationEntries, SimpleTranslationEntries } from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) export const PGMdialogue: DialogueTranslationEntries = { diff --git a/src/locales/en/egg.ts b/src/locales/en/egg.ts index b9ed9a71fd1..7009dc91b59 100644 --- a/src/locales/en/egg.ts +++ b/src/locales/en/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "Egg", diff --git a/src/locales/en/fight-ui-handler.ts b/src/locales/en/fight-ui-handler.ts index a73c5c6d3d6..8ceb503c34a 100644 --- a/src/locales/en/fight-ui-handler.ts +++ b/src/locales/en/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", diff --git a/src/locales/en/game-mode.ts b/src/locales/en/game-mode.ts index be342b4c390..903f1a63072 100644 --- a/src/locales/en/game-mode.ts +++ b/src/locales/en/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "Classic", diff --git a/src/locales/en/game-stats-ui-handler.ts b/src/locales/en/game-stats-ui-handler.ts index 64e4e2af5e3..06b2211b0dd 100644 --- a/src/locales/en/game-stats-ui-handler.ts +++ b/src/locales/en/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "Stats", diff --git a/src/locales/en/growth.ts b/src/locales/en/growth.ts index ea4dad72240..410355b143b 100644 --- a/src/locales/en/growth.ts +++ b/src/locales/en/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "Erratic", diff --git a/src/locales/en/menu-ui-handler.ts b/src/locales/en/menu-ui-handler.ts index 5958981968b..f34a87bb778 100644 --- a/src/locales/en/menu-ui-handler.ts +++ b/src/locales/en/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "Game Settings", diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 03b8f22332d..c7bade07a47 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,8 +34,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "Session loaded successfully.", "failedToLoadSession": "Your session data could not be loaded.\nIt may be corrupted.", "boyOrGirl": "Are you a boy or a girl?", - "boy": "Boy", - "girl": "Girl", "evolving": "What?\n{{pokemonName}} is evolving!", "stoppedEvolving": "{{pokemonName}} stopped evolving.", "pauseEvolutionsQuestion": "Would you like to pause evolutions for {{pokemonName}}?\nEvolutions can be re-enabled from the party screen.", @@ -44,11 +42,15 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", + "positionIcon": "#", + "usernameScoreboard": "Username", + "score": "Score", + "wave": "Wave", "loading": "Loading…", "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "Players Online", "yes":"Yes", "no":"No", "disclaimer": "DISCLAIMER", - "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed." + "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed.", } as const; diff --git a/src/locales/en/modifier-type.ts b/src/locales/en/modifier-type.ts index 3899e73dcac..f8073400358 100644 --- a/src/locales/en/modifier-type.ts +++ b/src/locales/en/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/en/move.ts b/src/locales/en/move.ts index 50f21186e2d..b9a8836dfec 100644 --- a/src/locales/en/move.ts +++ b/src/locales/en/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { "pound": { diff --git a/src/locales/en/nature.ts b/src/locales/en/nature.ts index 983252b9802..9ab26f3eb2a 100644 --- a/src/locales/en/nature.ts +++ b/src/locales/en/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "Hardy", diff --git a/src/locales/en/party-ui-handler.ts b/src/locales/en/party-ui-handler.ts index ec228863759..b7eac04b4c8 100644 --- a/src/locales/en/party-ui-handler.ts +++ b/src/locales/en/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "ALL": "All", diff --git a/src/locales/en/pokeball.ts b/src/locales/en/pokeball.ts index 6d69911efeb..01017cac46d 100644 --- a/src/locales/en/pokeball.ts +++ b/src/locales/en/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "Poké Ball", diff --git a/src/locales/en/pokemon-info-container.ts b/src/locales/en/pokemon-info-container.ts index 6b3ef954f58..0d37b2ead62 100644 --- a/src/locales/en/pokemon-info-container.ts +++ b/src/locales/en/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "Moveset", diff --git a/src/locales/en/pokemon-info.ts b/src/locales/en/pokemon-info.ts index f34ad219e7f..f31fdac69ab 100644 --- a/src/locales/en/pokemon-info.ts +++ b/src/locales/en/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { diff --git a/src/locales/en/pokemon.ts b/src/locales/en/pokemon.ts index 61c2d809082..297bbcc3975 100644 --- a/src/locales/en/pokemon.ts +++ b/src/locales/en/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "Bulbasaur", diff --git a/src/locales/en/save-slot-select-ui-handler.ts b/src/locales/en/save-slot-select-ui-handler.ts index 5aaa675fc4d..f4efa3de734 100644 --- a/src/locales/en/save-slot-select-ui-handler.ts +++ b/src/locales/en/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "Overwrite the data in the selected slot?", diff --git a/src/locales/en/settings.ts b/src/locales/en/settings.ts new file mode 100644 index 00000000000..20624defd92 --- /dev/null +++ b/src/locales/en/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "Boy", + "girl": "Girl", + "general": "General", + "display": "Display", + "audio": "Audio", + "gamepad": "Gamepad", + "keyboard": "Keyboard", + "gameSpeed": "Game Speed", + "hpBarSpeed": "HP Bar Speed", + "expGainsSpeed": "EXP Gains Speed", + "expPartyDisplay": "Show EXP Party", + "skipSeenDialogues": "Skip Seen Dialogues", + "battleStyle": "Battle Style", + "enableRetries": "Enable Retries", + "tutorials": "Tutorials", + "touchControls": "Touch Controls", + "vibrations": "Vibrations", + "normal": "Normal", + "fast": "Fast", + "faster": "Faster", + "skip": "Skip", + "levelUpNotifications": "Level Up Notifications", + "on": "On", + "off": "Off", + "switch": "Switch", + "set": "Set", + "auto": "Auto", + "disabled": "Disabled", + "language": "Language", + "change": "Change", + "uiTheme": "UI Theme", + "default": "Default", + "legacy": "Legacy", + "windowType": "Window Type", + "moneyFormat": "Money Format", + "damageNumbers": "Damage Numbers", + "simple": "Simple", + "fancy": "Fancy", + "abbreviated": "Abbreviated", + "moveAnimations": "Move Animations", + "showStatsOnLevelUp": "Show Stats on Level Up", + "candyUpgradeNotification": "Candy Upgrade Notification", + "passivesOnly": "Passives Only", + "candyUpgradeDisplay": "Candy Upgrade Display", + "icon": "Icon", + "animation": "Animation", + "moveInfo": "Move Info", + "showMovesetFlyout": "Show Moveset Flyout", + "showArenaFlyout": "Show Arena Flyout", + "showTimeOfDayWidget": "Show Time of Day Widget", + "timeOfDayAnimation": "Time of Day Animation", + "bounce": "Bounce", + "timeOfDay_back": "Back", + "spriteSet": "Sprite Set", + "consistent": "Consistent", + "mixedAnimated": "Mixed Animated", + "fusionPaletteSwaps": "Fusion Palette Swaps", + "playerGender": "Player Gender", + "typeHints": "Type Hints", + "masterVolume": "Master Volume", + "bgmVolume": "BGM Volume", + "seVolume": "SE Volume", + "musicPreference": "Music Preference", + "mixed": "Mixed", + "gamepadPleasePlug": "Please Plug in a Gamepad or Press a Button", + "delete": "Delete", + "keyboardPleasePress": "Please Press a Key on Your Keyboard", + "reset": "Reset", + "requireReload": "Reload Required", + "action": "Action", + "back": "Back", + "pressToBind": "Press to Bind", + "pressButton": "Press a Button...", + "buttonUp": "Up", + "buttonDown": "Down", + "buttonLeft": "Left", + "buttonRight": "Right", + "buttonAction": "Action", + "buttonMenu": "Menu", + "buttonSubmit": "Submit", + "buttonCancel": "Cancel", + "buttonStats": "Stats", + "buttonCycleForm": "Cycle Form", + "buttonCycleShiny": "Cycle Shiny", + "buttonCycleGender": "Cycle Gender", + "buttonCycleAbility": "Cycle Ability", + "buttonCycleNature": "Cycle Nature", + "buttonCycleVariant": "Cycle Variant", + "buttonSpeedUp": "Speed Up", + "buttonSlowDown": "Slow Down", + "alt": " (Alt)", + "mute": "Mute", + "controller": "Controller", + "gamepadSupport": "Gamepad Support" +} as const; diff --git a/src/locales/en/splash-messages.ts b/src/locales/en/splash-messages.ts index d8400111060..17eafc2d6d6 100644 --- a/src/locales/en/splash-messages.ts +++ b/src/locales/en/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "Battles Won!", diff --git a/src/locales/en/starter-select-ui-handler.ts b/src/locales/en/starter-select-ui-handler.ts index fd2eb6c40df..4b7c3194396 100644 --- a/src/locales/en/starter-select-ui-handler.ts +++ b/src/locales/en/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "addToParty": "Add to Party", "toggleIVs": "Toggle IVs", "manageMoves": "Manage Moves", + "manageNature": "Manage Nature", "useCandies": "Use Candies", + "selectNature": "Select nature.", "selectMoveSwapOut": "Select a move to swap out.", "selectMoveSwapWith": "Select a move to swap with", "unlockPassive": "Unlock Passive", diff --git a/src/locales/en/trainers.ts b/src/locales/en/trainers.ts index 39ca5f7512c..b59cfdc4fda 100644 --- a/src/locales/en/trainers.ts +++ b/src/locales/en/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/en/tutorial.ts b/src/locales/en/tutorial.ts index 6361bd7d25f..3c4aa2b46f6 100644 --- a/src/locales/en/tutorial.ts +++ b/src/locales/en/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `Welcome to PokéRogue! This is a battle-focused Pokémon fangame with roguelite elements. diff --git a/src/locales/en/voucher.ts b/src/locales/en/voucher.ts index f2bcb8d723c..57db5fe767f 100644 --- a/src/locales/en/voucher.ts +++ b/src/locales/en/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "Vouchers", @@ -8,4 +8,4 @@ export const voucher: SimpleTranslationEntries = { "eggVoucherGold": "Egg Voucher Gold", "locked": "Locked", "defeatTrainer": "Defeat {{trainerName}}" -} as const; +} as const; diff --git a/src/locales/en/weather.ts b/src/locales/en/weather.ts index 513c2181b00..f50c1ee907e 100644 --- a/src/locales/en/weather.ts +++ b/src/locales/en/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/es/ability-trigger.ts b/src/locales/es/ability-trigger.ts index e6dde7ad79f..0b0dcbd067b 100644 --- a/src/locales/es/ability-trigger.ts +++ b/src/locales/es/ability-trigger.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!", diff --git a/src/locales/es/ability.ts b/src/locales/es/ability.ts index 56f3afe6b02..d89bc6fa3cc 100644 --- a/src/locales/es/ability.ts +++ b/src/locales/es/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { "stench": { diff --git a/src/locales/es/achv.ts b/src/locales/es/achv.ts index 8d9ebc7d457..47348903b28 100644 --- a/src/locales/es/achv.ts +++ b/src/locales/es/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/es/battle-message-ui-handler.ts b/src/locales/es/battle-message-ui-handler.ts index e1668d1b5f6..cfc913f4b50 100644 --- a/src/locales/es/battle-message-ui-handler.ts +++ b/src/locales/es/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "Inmejorable", diff --git a/src/locales/es/battle.ts b/src/locales/es/battle.ts index 875421617de..76b6cd4e35e 100644 --- a/src/locales/es/battle.ts +++ b/src/locales/es/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "¡{{bossName}} te corta el paso!", @@ -70,4 +70,5 @@ export const battle: SimpleTranslationEntries = { "statHarshlyFell": "harshly fell", "statSeverelyFell": "severely fell", "statWontGoAnyLower": "won't go any lower", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/es/berry.ts b/src/locales/es/berry.ts index d2d891ea19c..0bebdf43c13 100644 --- a/src/locales/es/berry.ts +++ b/src/locales/es/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/es/biome.ts b/src/locales/es/biome.ts index 7e34c5285e5..a0b861b57f5 100644 --- a/src/locales/es/biome.ts +++ b/src/locales/es/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "En algún lugar que no puedes recordar", diff --git a/src/locales/es/challenges.ts b/src/locales/es/challenges.ts index 6c994e5f4b3..9bc5b0923fd 100644 --- a/src/locales/es/challenges.ts +++ b/src/locales/es/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "Parámetros de Desafíos", diff --git a/src/locales/es/command-ui-handler.ts b/src/locales/es/command-ui-handler.ts index 89dddb84a06..5ddde2c983a 100644 --- a/src/locales/es/command-ui-handler.ts +++ b/src/locales/es/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "Luchar", diff --git a/src/locales/es/config.ts b/src/locales/es/config.ts index 8b482de5c78..e85ba976be4 100644 --- a/src/locales/es/config.ts +++ b/src/locales/es/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/es/settings.js"; export const esConfig = { ability: ability, @@ -74,6 +75,7 @@ export const esConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/es/dialogue.ts b/src/locales/es/dialogue.ts index 48af5687cf2..5fed9019b29 100644 --- a/src/locales/es/dialogue.ts +++ b/src/locales/es/dialogue.ts @@ -1,4 +1,4 @@ -import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins/i18n"; +import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) export const PGMdialogue: DialogueTranslationEntries = { @@ -2109,28 +2109,28 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "alder": { "encounter": { - 1: "Prepare yourself for a match against the strongest Trainer in Unova!" + 1: "Prepárate para una batalla contra el entrenador más fuerte en Unova!" }, "victory": { - 1: "Well done! You certainly are an unmatched talent." + 1: "Bien hecho! Tienes ciertamente un talento inigualable" }, "defeat": { - 1: `A fresh wind blows through my heart... - $What an extraordinary effort!` + 1: `Un viento fresco sopla a través en mi corazón + $Qué esfuerzo extraordinario!` } }, "kieran": { "encounter": { - 1: `Through hard work, I become stronger and stronger! - $I don't lose.` + 1: `A través del trabajo duro, me he vuelto más y más fuerte! + $No pierdo.` }, "victory": { - 1: `I don't believe it... - $What a fun and heart-pounding battle!` + 1: `No puedo creerlo... + $¡Qué batalla tan divertida y trepidante!` }, "defeat": { - 1: `Wowzers, what a battle! - $Time for you to train even harder.` + 1: `Asombroso, que batalla! + $Es hora de que entrenes aún más duro.` } }, "rival": { diff --git a/src/locales/es/egg.ts b/src/locales/es/egg.ts index cdce119507a..d04f74ed8ef 100644 --- a/src/locales/es/egg.ts +++ b/src/locales/es/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "Huevo", diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts index 6c6afec1daf..70526ce4692 100644 --- a/src/locales/es/fight-ui-handler.ts +++ b/src/locales/es/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", diff --git a/src/locales/es/game-mode.ts b/src/locales/es/game-mode.ts index dcff983791f..bf399b8fc74 100644 --- a/src/locales/es/game-mode.ts +++ b/src/locales/es/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "Clásica", diff --git a/src/locales/es/game-stats-ui-handler.ts b/src/locales/es/game-stats-ui-handler.ts index 64e4e2af5e3..06b2211b0dd 100644 --- a/src/locales/es/game-stats-ui-handler.ts +++ b/src/locales/es/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "Stats", diff --git a/src/locales/es/growth.ts b/src/locales/es/growth.ts index a47a4f408bd..c72ea3d76c6 100644 --- a/src/locales/es/growth.ts +++ b/src/locales/es/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "Errático", diff --git a/src/locales/es/menu-ui-handler.ts b/src/locales/es/menu-ui-handler.ts index 76972cef19c..ff0e38f110a 100644 --- a/src/locales/es/menu-ui-handler.ts +++ b/src/locales/es/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "Ajustes", diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 4bd6d750d69..c47406a0e95 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,8 +34,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "Sesión cargada con éxito.", "failedToLoadSession": "No se han podido cargar los datos de tu sesión.\nPuede que estén corruptos.", "boyOrGirl": "¿Eres un chico o una chica?", - "boy": "Chico", - "girl": "Chica", "evolving": "¡Anda!\n¡{{pokemonName}} está evolucionando!", "stoppedEvolving": "¿Eh?\n¡La evolución de {{pokemonName}} se ha detenido!", "pauseEvolutionsQuestion": "¿Quieres detener las evoluciones de {{pokemonName}}?\nSiempre pueden ser reactivadas desde la pantalla de tu equipo.", @@ -44,11 +42,15 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "Rankings Diarios", "weeklyRankings": "Rankings Semanales", "noRankings": "Sin Rankings", + "positionIcon": "#", + "usernameScoreboard": "Username", + "score": "Score", + "wave": "Wave", "loading": "Cargando…", "loadingAsset": "Cargando recurso: {{assetName}}", "playersOnline": "Jugadores en Línea", "yes":"Sí", "no":"No", "disclaimer": "AVISO", - "disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida de datos de guardado),\ncambiar sin avisar, y puede o no puede ser actualizado hasta ser completado." + "disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida\n de datos de guardado),cambiar sin avisar, y puede o no puede ser actualizado hasta ser completado.", } as const; diff --git a/src/locales/es/modifier-type.ts b/src/locales/es/modifier-type.ts index 5689f039f5c..8bdb6f13f41 100644 --- a/src/locales/es/modifier-type.ts +++ b/src/locales/es/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/es/move.ts b/src/locales/es/move.ts index 7bf63008aeb..3693e008574 100644 --- a/src/locales/es/move.ts +++ b/src/locales/es/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { pound: { diff --git a/src/locales/es/nature.ts b/src/locales/es/nature.ts index 212ee403bd7..ddeff5aa0ab 100644 --- a/src/locales/es/nature.ts +++ b/src/locales/es/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "Fuerte", diff --git a/src/locales/es/party-ui-handler.ts b/src/locales/es/party-ui-handler.ts index 9d3c7baa9ae..894ea14bb12 100644 --- a/src/locales/es/party-ui-handler.ts +++ b/src/locales/es/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "SEND_OUT": "Send Out", diff --git a/src/locales/es/pokeball.ts b/src/locales/es/pokeball.ts index a38b6d6a047..c9b62cdd9ea 100644 --- a/src/locales/es/pokeball.ts +++ b/src/locales/es/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "Poké Ball", diff --git a/src/locales/es/pokemon-info-container.ts b/src/locales/es/pokemon-info-container.ts index 785f5fce275..ad0f951b984 100644 --- a/src/locales/es/pokemon-info-container.ts +++ b/src/locales/es/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "Movimientos", diff --git a/src/locales/es/pokemon-info.ts b/src/locales/es/pokemon-info.ts index d3a39c83b44..56fd7130c0a 100644 --- a/src/locales/es/pokemon-info.ts +++ b/src/locales/es/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { diff --git a/src/locales/es/pokemon.ts b/src/locales/es/pokemon.ts index b230777e033..93f13aed8b0 100644 --- a/src/locales/es/pokemon.ts +++ b/src/locales/es/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "Bulbasaur", diff --git a/src/locales/es/save-slot-select-ui-handler.ts b/src/locales/es/save-slot-select-ui-handler.ts index 7939518ceed..645afd453a9 100644 --- a/src/locales/es/save-slot-select-ui-handler.ts +++ b/src/locales/es/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "¿Sobrescribir los datos en la ranura seleccionada?", diff --git a/src/locales/es/settings.ts b/src/locales/es/settings.ts new file mode 100644 index 00000000000..bf4c22707a9 --- /dev/null +++ b/src/locales/es/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "Chico", + "girl": "Chica", + "general": "General", + "display": "Display", + "audio": "Audio", + "gamepad": "Gamepad", + "keyboard": "Keyboard", + "gameSpeed": "Game Speed", + "hpBarSpeed": "HP Bar Speed", + "expGainsSpeed": "EXP Gains Speed", + "expPartyDisplay": "Show EXP Party", + "skipSeenDialogues": "Skip Seen Dialogues", + "battleStyle": "Battle Style", + "enableRetries": "Enable Retries", + "tutorials": "Tutorials", + "touchControls": "Touch Controls", + "vibrations": "Vibrations", + "normal": "Normal", + "fast": "Fast", + "faster": "Faster", + "skip": "Skip", + "levelUpNotifications": "Level Up Notifications", + "on": "On", + "off": "Off", + "switch": "Switch", + "set": "Set", + "auto": "Auto", + "disabled": "Disabled", + "language": "Language", + "change": "Change", + "uiTheme": "UI Theme", + "default": "Default", + "legacy": "Legacy", + "windowType": "Window Type", + "moneyFormat": "Money Format", + "damageNumbers": "Damage Numbers", + "simple": "Simple", + "fancy": "Fancy", + "abbreviated": "Abbreviated", + "moveAnimations": "Move Animations", + "showStatsOnLevelUp": "Show Stats on Level Up", + "candyUpgradeNotification": "Candy Upgrade Notification", + "passivesOnly": "Passives Only", + "candyUpgradeDisplay": "Candy Upgrade Display", + "icon": "Icon", + "animation": "Animation", + "moveInfo": "Move Info", + "showMovesetFlyout": "Show Moveset Flyout", + "showArenaFlyout": "Show Arena Flyout", + "showTimeOfDayWidget": "Show Time of Day Widget", + "timeOfDayAnimation": "Time of Day Animation", + "bounce": "Bounce", + "timeOfDay_back": "Back", + "spriteSet": "Sprite Set", + "consistent": "Consistent", + "mixedAnimated": "Mixed Animated", + "fusionPaletteSwaps": "Fusion Palette Swaps", + "playerGender": "Player Gender", + "typeHints": "Type Hints", + "masterVolume": "Master Volume", + "bgmVolume": "BGM Volume", + "seVolume": "SE Volume", + "musicPreference": "Music Preference", + "mixed": "Mixed", + "gamepadPleasePlug": "Please Plug in a Gamepad or Press a Button", + "delete": "Delete", + "keyboardPleasePress": "Please Press a Key on Your Keyboard", + "reset": "Reset", + "requireReload": "Reload Required", + "action": "Action", + "back": "Back", + "pressToBind": "Press to Bind", + "pressButton": "Press a Button...", + "buttonUp": "Up", + "buttonDown": "Down", + "buttonLeft": "Left", + "buttonRight": "Right", + "buttonAction": "Action", + "buttonMenu": "Menu", + "buttonSubmit": "Submit", + "buttonCancel": "Cancel", + "buttonStats": "Stats", + "buttonCycleForm": "Cycle Form", + "buttonCycleShiny": "Cycle Shiny", + "buttonCycleGender": "Cycle Gender", + "buttonCycleAbility": "Cycle Ability", + "buttonCycleNature": "Cycle Nature", + "buttonCycleVariant": "Cycle Variant", + "buttonSpeedUp": "Speed Up", + "buttonSlowDown": "Slow Down", + "alt": " (Alt)", + "mute": "Mute", + "controller": "Controller", + "gamepadSupport": "Gamepad Support" +} as const; diff --git a/src/locales/es/splash-messages.ts b/src/locales/es/splash-messages.ts index 665476da1fb..0d6f050be94 100644 --- a/src/locales/es/splash-messages.ts +++ b/src/locales/es/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "¡Batallas ganadas!", diff --git a/src/locales/es/starter-select-ui-handler.ts b/src/locales/es/starter-select-ui-handler.ts index 4d025820260..642d55ab5d8 100644 --- a/src/locales/es/starter-select-ui-handler.ts +++ b/src/locales/es/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "addToParty": "Añadir a Equipo", "toggleIVs": "Mostrar IVs", "manageMoves": "Gestionar Movs.", + "manageNature": "Gestionar Natur", "useCandies": "Usar Caramelos", + "selectNature": "Elige Natur.", "selectMoveSwapOut": "Elige el movimiento que sustituir.", "selectMoveSwapWith": "Elige el movimiento que sustituirá a", "unlockPassive": "Añadir Pasiva", diff --git a/src/locales/es/trainers.ts b/src/locales/es/trainers.ts index 6d776f44c9c..d5647f83cf6 100644 --- a/src/locales/es/trainers.ts +++ b/src/locales/es/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/es/tutorial.ts b/src/locales/es/tutorial.ts index 055bc808da3..5a33bcd9dd0 100644 --- a/src/locales/es/tutorial.ts +++ b/src/locales/es/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `¡Bienvenido/a a PokéRogue! Este es un fangame de Pokémon centrado en el combate con elementos roguelite. diff --git a/src/locales/es/voucher.ts b/src/locales/es/voucher.ts index 86debdc25cf..60479160efe 100644 --- a/src/locales/es/voucher.ts +++ b/src/locales/es/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "Vales", diff --git a/src/locales/es/weather.ts b/src/locales/es/weather.ts index 1e40544accd..5565779a7bd 100644 --- a/src/locales/es/weather.ts +++ b/src/locales/es/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/fr/ability-trigger.ts b/src/locales/fr/ability-trigger.ts index cad8183cd6b..90a2a9ac109 100644 --- a/src/locales/fr/ability-trigger.ts +++ b/src/locales/fr/ability-trigger.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !", diff --git a/src/locales/fr/ability.ts b/src/locales/fr/ability.ts index f984c8843de..a69519e187a 100644 --- a/src/locales/fr/ability.ts +++ b/src/locales/fr/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { stench: { diff --git a/src/locales/fr/achv.ts b/src/locales/fr/achv.ts index 3914a14c044..4ff9bf20f51 100644 --- a/src/locales/fr/achv.ts +++ b/src/locales/fr/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/fr/battle-message-ui-handler.ts b/src/locales/fr/battle-message-ui-handler.ts index 8dc980d49a4..cb2f745577e 100644 --- a/src/locales/fr/battle-message-ui-handler.ts +++ b/src/locales/fr/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "Exceptionnel", diff --git a/src/locales/fr/battle.ts b/src/locales/fr/battle.ts index 3bb051830ee..e270539c781 100644 --- a/src/locales/fr/battle.ts +++ b/src/locales/fr/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "Un {{bossName}} apparait.", @@ -70,4 +70,5 @@ export const battle: SimpleTranslationEntries = { "statHarshlyFell": "harshly fell", "statSeverelyFell": "severely fell", "statWontGoAnyLower": "won't go any lower", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/fr/berry.ts b/src/locales/fr/berry.ts index dd6b387f4cc..b5048eb02c0 100644 --- a/src/locales/fr/berry.ts +++ b/src/locales/fr/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/fr/biome.ts b/src/locales/fr/biome.ts index 2f3dffb28f6..83029b3a8d4 100644 --- a/src/locales/fr/biome.ts +++ b/src/locales/fr/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "vous avez oublié où", diff --git a/src/locales/fr/challenges.ts b/src/locales/fr/challenges.ts index 351733d6c52..6029cdc302a 100644 --- a/src/locales/fr/challenges.ts +++ b/src/locales/fr/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "Paramètres du Challenge", diff --git a/src/locales/fr/command-ui-handler.ts b/src/locales/fr/command-ui-handler.ts index 37d910c8844..42180d31276 100644 --- a/src/locales/fr/command-ui-handler.ts +++ b/src/locales/fr/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "Attaque", diff --git a/src/locales/fr/config.ts b/src/locales/fr/config.ts index f7b7467c4bc..b5e7a4e383a 100644 --- a/src/locales/fr/config.ts +++ b/src/locales/fr/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/fr/settings.js"; export const frConfig = { ability: ability, @@ -74,6 +75,7 @@ export const frConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/fr/dialogue.ts b/src/locales/fr/dialogue.ts index 5887bbe5710..382e9a179fe 100644 --- a/src/locales/fr/dialogue.ts +++ b/src/locales/fr/dialogue.ts @@ -1,4 +1,4 @@ -import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins/i18n"; +import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) export const PGMdialogue: DialogueTranslationEntries = { @@ -2109,28 +2109,28 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "alder": { "encounter": { - 1: "Prepare yourself for a match against the strongest Trainer in Unova!" + 1: "Prépare-toi pour un combat contre le meilleur Dresseur d'Unys !", }, "victory": { - 1: "Well done! You certainly are an unmatched talent." + 1: "Bien joué ! Tu as sans aucun doute un talent inégalé.", }, "defeat": { - 1: `A fresh wind blows through my heart... - $What an extraordinary effort!` + 1: `Une brise fraîche traverse mon cœur… + $Quel effort extraordinaire !`, } }, "kieran": { "encounter": { - 1: `Through hard work, I become stronger and stronger! - $I don't lose.` + 1: `Grâce à un travail acharné, je deviens de plus en plus fort ! + $Je ne perdrai pas.`, }, "victory": { - 1: `I don't believe it... - $What a fun and heart-pounding battle!` + 1: `Je n'y crois pas… + $Quel combat amusant et palpitant !` }, "defeat": { - 1: `Wowzers, what a battle! - $Time for you to train even harder.` + 1: `Eh beh, quel combat ! + $Il est temps pour toi de t'entraîner encore plus dur.`, } }, "rival": { diff --git a/src/locales/fr/egg.ts b/src/locales/fr/egg.ts index beffb1a98a7..b7df2d51cc7 100644 --- a/src/locales/fr/egg.ts +++ b/src/locales/fr/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "Œuf", diff --git a/src/locales/fr/fight-ui-handler.ts b/src/locales/fr/fight-ui-handler.ts index 723524ae2af..5472838d780 100644 --- a/src/locales/fr/fight-ui-handler.ts +++ b/src/locales/fr/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", diff --git a/src/locales/fr/game-mode.ts b/src/locales/fr/game-mode.ts index 28858e46bfa..ad4481b4953 100644 --- a/src/locales/fr/game-mode.ts +++ b/src/locales/fr/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "Classique", diff --git a/src/locales/fr/game-stats-ui-handler.ts b/src/locales/fr/game-stats-ui-handler.ts index 1f368f1ff43..6d6bcd370d2 100644 --- a/src/locales/fr/game-stats-ui-handler.ts +++ b/src/locales/fr/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "Statistiques", diff --git a/src/locales/fr/growth.ts b/src/locales/fr/growth.ts index a4e9e8ed0ce..f44913b7d60 100644 --- a/src/locales/fr/growth.ts +++ b/src/locales/fr/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "Erratique", diff --git a/src/locales/fr/menu-ui-handler.ts b/src/locales/fr/menu-ui-handler.ts index 9494a64ab3f..2a9eecd66ec 100644 --- a/src/locales/fr/menu-ui-handler.ts +++ b/src/locales/fr/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "Paramètres", diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index f9538e9d26c..8b13335fe57 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menu: SimpleTranslationEntries = { "cancel": "Annuler", @@ -29,8 +29,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "Session chargée avec succès.", "failedToLoadSession": "Vos données de session n’ont pas pu être chargées.\nElles pourraient être corrompues.", "boyOrGirl": "Es-tu un garçon ou une fille ?", - "boy": "Garçon", - "girl": "Fille", "evolving": "Quoi ?\n{{pokemonName}} évolue !", "stoppedEvolving": "Hein ?\n{{pokemonName}} n’évolue plus !", "pauseEvolutionsQuestion": "Mettre en pause les évolutions pour {{pokemonName}} ?\nElles peuvent être réactivées depuis l’écran d’équipe.", @@ -39,11 +37,15 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "Classement du Jour", "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", + "positionIcon": "#", + "usernameScoreboard": "Username", + "score": "Score", + "wave": "Wave", "loading": "Chargement…", - "loadingAsset": "Loading asset: {{assetName}}", + "loadingAsset": "Chargement de la ressource: {{assetName}}", "playersOnline": "Joueurs Connectés", "yes":"Oui", "no":"Non", "disclaimer": "AVERTISSEMENT", - "disclaimerDescription": "Ce jeu n’est pas un produit fini et peut contenir des problèmes de jouabilité, dont de possibles pertes de sauvegardes,\ndes modifications sans avertissement et pourrait ou non encore être mis à jour ou terminé." + "disclaimerDescription": "Ce jeu n’est pas un produit fini et peut contenir des problèmes de jouabilité, dont de possibles pertes de sauvegardes,\ndes modifications sans avertissement et pourrait ou non encore être mis à jour ou terminé.", } as const; diff --git a/src/locales/fr/modifier-type.ts b/src/locales/fr/modifier-type.ts index 9ef99f49330..97a31161dc4 100644 --- a/src/locales/fr/modifier-type.ts +++ b/src/locales/fr/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/fr/move.ts b/src/locales/fr/move.ts index cd67d592919..3fea8995694 100644 --- a/src/locales/fr/move.ts +++ b/src/locales/fr/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { "pound": { diff --git a/src/locales/fr/nature.ts b/src/locales/fr/nature.ts index 0c838138bfe..6f2e3985d8f 100644 --- a/src/locales/fr/nature.ts +++ b/src/locales/fr/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "Hardi", diff --git a/src/locales/fr/party-ui-handler.ts b/src/locales/fr/party-ui-handler.ts index 3c76bf8fb6a..369f7b65bb9 100644 --- a/src/locales/fr/party-ui-handler.ts +++ b/src/locales/fr/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "ALL": "Tout", diff --git a/src/locales/fr/pokeball.ts b/src/locales/fr/pokeball.ts index 0f878eea528..910002e41e1 100644 --- a/src/locales/fr/pokeball.ts +++ b/src/locales/fr/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "Poké Ball", diff --git a/src/locales/fr/pokemon-info-container.ts b/src/locales/fr/pokemon-info-container.ts index 52813725c18..c61c23b0970 100644 --- a/src/locales/fr/pokemon-info-container.ts +++ b/src/locales/fr/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "Capacités", diff --git a/src/locales/fr/pokemon-info.ts b/src/locales/fr/pokemon-info.ts index 373106d732b..641b372f3d3 100644 --- a/src/locales/fr/pokemon-info.ts +++ b/src/locales/fr/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { diff --git a/src/locales/fr/pokemon.ts b/src/locales/fr/pokemon.ts index d685f91ab4d..d731fd148ad 100644 --- a/src/locales/fr/pokemon.ts +++ b/src/locales/fr/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "Bulbizarre", diff --git a/src/locales/fr/save-slot-select-ui-handler.ts b/src/locales/fr/save-slot-select-ui-handler.ts index 53b68191b9f..64f6da7017c 100644 --- a/src/locales/fr/save-slot-select-ui-handler.ts +++ b/src/locales/fr/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "Effacer les données de l’emplacement sélectionné ?", diff --git a/src/locales/fr/settings.ts b/src/locales/fr/settings.ts new file mode 100644 index 00000000000..59de6c82d32 --- /dev/null +++ b/src/locales/fr/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "Garçon", + "girl": "Fille", + "general": "Général", + "display": "Affichage", + "audio": "Audio", + "gamepad": "Manette", + "keyboard": "Clavier", + "gameSpeed": "Vitesse du jeu", + "hpBarSpeed": "Vit. barre de PV", + "expGainsSpeed": "Vit.barre d’Exp", + "expPartyDisplay": "Afficher Exp équipe", + "skipSeenDialogues": "Passer dialogues connus", + "battleStyle": "Style de combat", + "enableRetries": "Activer les réessais", + "tutorials": "Tutoriels", + "touchControls": "Contrôles tactiles", + "vibrations": "Vibrations", + "normal": "Normal", + "fast": "Rapide", + "faster": "Plus rapide", + "skip": "Passer", + "levelUpNotifications": "Notif. gain de N.", + "on": "Activé", + "off": "Désactivé", + "switch": "Choix", + "set": "Défini", + "auto": "Auto", + "disabled": "Désactivé", + "language": "Langue", + "change": "Changer", + "uiTheme": "Interface", + "default": "Par défaut", + "legacy": "Ancienne", + "windowType": "Type de fenêtre", + "moneyFormat": "Format de l’argent", + "damageNumbers": "Nombres de dégâts", + "simple": "Simple", + "fancy": "Amélioré", + "abbreviated": "Abrégé", + "moveAnimations": "Animations de combat", + "showStatsOnLevelUp": "Afficher stats à la montée de niveau", + "candyUpgradeNotification": "Notif amélioration de bonbon", + "passivesOnly": "Passifs", + "candyUpgradeDisplay": "Amélioration bonbon", + "icon": "Icône", + "animation": "Animation", + "moveInfo": "Info de capacité", + "showMovesetFlyout": "Afficher le volet de capacités", + "showArenaFlyout": "Afficher le volet d’arène", + "showTimeOfDayWidget": "Widget de l’heure", + "timeOfDayAnimation": "Animation de l’heure", + "bounce": "Sauter", + "timeOfDay_back": "Retour", + "spriteSet": "Ensemble de sprites", + "consistent": "Consistant", + "mixedAnimated": "Mixte", + "fusionPaletteSwaps": "Palettes de fusion", + "playerGender": "Genre du joueur", + "typeHints": "Indications de type", + "masterVolume": "Vol. principal", + "bgmVolume": "Vol. musique", + "seVolume": "Vol. effets", + "musicPreference": "Préférence musicale", + "mixed": "Mixte", + "gamepadPleasePlug": "Veuillez brancher une manette ou appuyer sur un bouton", + "delete": "Supprimer", + "keyboardPleasePress": "Veuillez appuyer sur une touche de votre clavier", + "reset": "Réinitialiser", + "requireReload": "Redémarrage requis", + "action": "Action", + "back": "Retour", + "pressToBind": "Sélectionnez pour assigner", + "pressButton": "Appuyez sur un bouton…", + "buttonUp": "Haut", + "buttonDown": "Bas", + "buttonLeft": "Gauche", + "buttonRight": "Droite", + "buttonAction": "Action", + "buttonMenu": "Menu", + "buttonSubmit": "Valider", + "buttonCancel": "Annuler", + "buttonStats": "Stats", + "buttonCycleForm": "Modifier Forme", + "buttonCycleShiny": "Modifier Chromatique", + "buttonCycleGender": "Modifier Sexe", + "buttonCycleAbility": "Modifier Capacité", + "buttonCycleNature": "Modifier Nature", + "buttonCycleVariant": "Modifier Variant", + "buttonSpeedUp": "Accélérer", + "buttonSlowDown": "Ralentir", + "alt": " (Alt)", + "mute": "Mute", + "controller": "Controller", + "gamepadSupport": "Gamepad Support" +} as const; diff --git a/src/locales/fr/splash-messages.ts b/src/locales/fr/splash-messages.ts index f1ce65e987c..13de7f28116 100644 --- a/src/locales/fr/splash-messages.ts +++ b/src/locales/fr/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "combats gagnés !", diff --git a/src/locales/fr/starter-select-ui-handler.ts b/src/locales/fr/starter-select-ui-handler.ts index 9f504cab11e..0874c18d84c 100644 --- a/src/locales/fr/starter-select-ui-handler.ts +++ b/src/locales/fr/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -23,9 +23,11 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "eggMoves": "Capacités Œuf", "start": "Lancer", "addToParty": "Ajouter à l’équipe", - "toggleIVs": "Voir IVs", - "manageMoves": "Gérer Capacités", - "useCandies": "Utiliser Bonbons", + "toggleIVs": "Voir les IV", + "manageMoves": "Modifier les Capacités", + "manageNature": "Modifier la Nature", + "useCandies": "Utiliser des Bonbons", + "selectNature": "Sélectionnez une nature.", "selectMoveSwapOut": "Sélectionnez la capacité à échanger.", "selectMoveSwapWith": "Sélectionnez laquelle échanger avec", "unlockPassive": "Débloquer Passif", diff --git a/src/locales/fr/trainers.ts b/src/locales/fr/trainers.ts index 3e7518ec164..fc0639d47b9 100644 --- a/src/locales/fr/trainers.ts +++ b/src/locales/fr/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/fr/tutorial.ts b/src/locales/fr/tutorial.ts index 2f12f7ccaa0..d8940dadd56 100644 --- a/src/locales/fr/tutorial.ts +++ b/src/locales/fr/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `Bienvenue dans PokéRogue, un fangame axé sur les combats Pokémon avec des éléments roguelite ! diff --git a/src/locales/fr/voucher.ts b/src/locales/fr/voucher.ts index ba787ec05a7..7cab3f90878 100644 --- a/src/locales/fr/voucher.ts +++ b/src/locales/fr/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "Coupons", @@ -8,4 +8,4 @@ export const voucher: SimpleTranslationEntries = { "eggVoucherGold": "Coupon Œuf Or", "locked": "Verrouillé", "defeatTrainer": "Vaincre {{trainerName}}" -} as const; +} as const; diff --git a/src/locales/fr/weather.ts b/src/locales/fr/weather.ts index 5c483d71b44..fa6090a3ad5 100644 --- a/src/locales/fr/weather.ts +++ b/src/locales/fr/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/it/ability-trigger.ts b/src/locales/it/ability-trigger.ts index 527c1e4fead..17dbfd89fb1 100644 --- a/src/locales/it/ability-trigger.ts +++ b/src/locales/it/ability-trigger.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{abilityName}} di {{pokemonName}}\nl'ha protetto dal contraccolpo!", diff --git a/src/locales/it/ability.ts b/src/locales/it/ability.ts index 9eb9480f771..5e01e02a718 100644 --- a/src/locales/it/ability.ts +++ b/src/locales/it/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { stench: { diff --git a/src/locales/it/achv.ts b/src/locales/it/achv.ts index 68ad935aed8..0ec9ad3f98a 100644 --- a/src/locales/it/achv.ts +++ b/src/locales/it/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/it/battle-message-ui-handler.ts b/src/locales/it/battle-message-ui-handler.ts index 33aabb61fb1..d70ab400e39 100644 --- a/src/locales/it/battle-message-ui-handler.ts +++ b/src/locales/it/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "Stellare", @@ -7,4 +7,4 @@ export const battleMessageUiHandler: SimpleTranslationEntries = { "ivPrettyGood": "Normale", "ivDecent": "Sufficiente", "ivNoGood": "Mediocre", -} as const; +} as const; diff --git a/src/locales/it/battle.ts b/src/locales/it/battle.ts index 8fb9cf56c70..4f90a361ecb 100644 --- a/src/locales/it/battle.ts +++ b/src/locales/it/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} è apparso.", @@ -70,4 +70,5 @@ export const battle: SimpleTranslationEntries = { "statHarshlyFell": "harshly fell", "statSeverelyFell": "severely fell", "statWontGoAnyLower": "won't go any lower", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/it/berry.ts b/src/locales/it/berry.ts index 4c36e209f64..7be40b43c32 100644 --- a/src/locales/it/berry.ts +++ b/src/locales/it/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/it/biome.ts b/src/locales/it/biome.ts index f914d96e13f..602218fa852 100644 --- a/src/locales/it/biome.ts +++ b/src/locales/it/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "Da qualche parte che non ricordi", diff --git a/src/locales/it/challenges.ts b/src/locales/it/challenges.ts index 8e9d3b9ef47..0a15b22f83e 100644 --- a/src/locales/it/challenges.ts +++ b/src/locales/it/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "Modificatori delle sfide", diff --git a/src/locales/it/command-ui-handler.ts b/src/locales/it/command-ui-handler.ts index 7c30532d46c..acd0370ba05 100644 --- a/src/locales/it/command-ui-handler.ts +++ b/src/locales/it/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "Lotta", diff --git a/src/locales/it/config.ts b/src/locales/it/config.ts index 333c11ae6a8..6f14aabda50 100644 --- a/src/locales/it/config.ts +++ b/src/locales/it/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/it/settings.js"; export const itConfig = { ability: ability, @@ -74,6 +75,7 @@ export const itConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/it/dialogue.ts b/src/locales/it/dialogue.ts index 83e72036841..0fbd8cabf67 100644 --- a/src/locales/it/dialogue.ts +++ b/src/locales/it/dialogue.ts @@ -1,4 +1,4 @@ -import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins/i18n"; +import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) export const PGMdialogue: DialogueTranslationEntries = { @@ -2109,28 +2109,28 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "alder": { "encounter": { - 1: "Prepare yourself for a match against the strongest Trainer in Unova!" + 1: "Preparati ad affrontare l’allenatore più in gamba di Unima!" }, "victory": { - 1: "Well done! You certainly are an unmatched talent." + 1: "Ben fatto! Hai un talento invidiabile." }, "defeat": { - 1: `A fresh wind blows through my heart... - $What an extraordinary effort!` + 1: `Un freddo vento attraversa il mio cuore... + $Che battaglia!` } }, "kieran": { "encounter": { - 1: `Through hard work, I become stronger and stronger! - $I don't lose.` + 1: `Attraverso il duro lavoro, divento sempre più forte! + $Non perdo mai.` }, "victory": { - 1: `I don't believe it... - $What a fun and heart-pounding battle!` + 1: `Non posso crederci… + $Che battaglia mozzafiato!` }, "defeat": { - 1: `Wowzers, what a battle! - $Time for you to train even harder.` + 1: `Cavoli, che scontro! + $È ora che tu ti alleni ancora più duramente.` } }, "rival": { diff --git a/src/locales/it/egg.ts b/src/locales/it/egg.ts index e486122280b..63c8290edee 100644 --- a/src/locales/it/egg.ts +++ b/src/locales/it/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "Uovo", diff --git a/src/locales/it/fight-ui-handler.ts b/src/locales/it/fight-ui-handler.ts index de756fa4c93..91f1c3c19f4 100644 --- a/src/locales/it/fight-ui-handler.ts +++ b/src/locales/it/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", diff --git a/src/locales/it/game-mode.ts b/src/locales/it/game-mode.ts index 78d44b5bf5c..88bc39e4a76 100644 --- a/src/locales/it/game-mode.ts +++ b/src/locales/it/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "Classica", diff --git a/src/locales/it/game-stats-ui-handler.ts b/src/locales/it/game-stats-ui-handler.ts index 9843fb1a655..f4b5f80e23b 100644 --- a/src/locales/it/game-stats-ui-handler.ts +++ b/src/locales/it/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "Statistiche", diff --git a/src/locales/it/growth.ts b/src/locales/it/growth.ts index 96edcac4d93..8132137d9fe 100644 --- a/src/locales/it/growth.ts +++ b/src/locales/it/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "Irregolare", diff --git a/src/locales/it/menu-ui-handler.ts b/src/locales/it/menu-ui-handler.ts index 336fd997918..9a1e16a77b5 100644 --- a/src/locales/it/menu-ui-handler.ts +++ b/src/locales/it/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "Impostazioni", diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 07af8ee70e9..187743a7921 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,11 +34,13 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "Sessione caricata correttamente.", "failedToLoadSession": "Impossibile caricare i dati della sessione.\nPotrebbero essere danneggiati.", "boyOrGirl": "Sei un ragazzo o una ragazza?", - "boy": "Ragazzo", - "girl": "Ragazza", "dailyRankings": "Classifica giornaliera", "weeklyRankings": "Classifica settimanale", "noRankings": "Nessuna classifica", + "positionIcon": "#", + "usernameScoreboard": "Username", + "score": "Score", + "wave": "Wave", "loading": "Caricamento…", "loadingAsset": "Caricamento asset: {{assetName}}", "playersOnline": "Giocatori online", @@ -50,5 +52,5 @@ export const menu: SimpleTranslationEntries = { "yes":"Si", "no":"No", "disclaimer": "DISCLAIMER", - "disclaimerDescription": "Questo gioco è un prodotto incompleto; si potrebbero riscontrare errori (inclusa la perdita dei dati di salvataggio),\ncambiamenti impercettibili, e non è detto che venga aggiornato nel tempo o mai completato del tutto." + "disclaimerDescription": "Questo gioco è un prodotto incompleto; si potrebbero riscontrare errori (inclusa la perdita dei dati di salvataggio),\ncambiamenti impercettibili, e non è detto che venga aggiornato nel tempo o mai completato del tutto.", } as const; diff --git a/src/locales/it/modifier-type.ts b/src/locales/it/modifier-type.ts index 44006a3f76a..07e7e6909f4 100644 --- a/src/locales/it/modifier-type.ts +++ b/src/locales/it/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/it/move.ts b/src/locales/it/move.ts index 677fcda093a..a7ebd605f18 100644 --- a/src/locales/it/move.ts +++ b/src/locales/it/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { pound: { diff --git a/src/locales/it/nature.ts b/src/locales/it/nature.ts index 401567901ad..3c6e8b4d29f 100644 --- a/src/locales/it/nature.ts +++ b/src/locales/it/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "Ardita", diff --git a/src/locales/it/party-ui-handler.ts b/src/locales/it/party-ui-handler.ts index 486e711b96f..c174df03d1f 100644 --- a/src/locales/it/party-ui-handler.ts +++ b/src/locales/it/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "SEND_OUT": "Manda in campo", diff --git a/src/locales/it/pokeball.ts b/src/locales/it/pokeball.ts index ad43c652478..df556415670 100644 --- a/src/locales/it/pokeball.ts +++ b/src/locales/it/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "Poké Ball", diff --git a/src/locales/it/pokemon-info-container.ts b/src/locales/it/pokemon-info-container.ts index b1bd585363d..2d80763abc3 100644 --- a/src/locales/it/pokemon-info-container.ts +++ b/src/locales/it/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "Set di mosse", diff --git a/src/locales/it/pokemon-info.ts b/src/locales/it/pokemon-info.ts index b1be48c5e63..9d8780e656b 100644 --- a/src/locales/it/pokemon-info.ts +++ b/src/locales/it/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { @@ -14,8 +14,8 @@ export const pokemonInfo: PokemonInfoTranslationEntries = { "SPDEFshortened": "DifSp", "SPD": "Velocità", "SPDshortened": "Vel", - "ACC": "Accuracy", - "EVA": "Evasiveness" + "ACC": "Precisione", + "EVA": "Elusione" }, Type: { diff --git a/src/locales/it/pokemon.ts b/src/locales/it/pokemon.ts index 400a34e6e8b..8d0830aeb79 100644 --- a/src/locales/it/pokemon.ts +++ b/src/locales/it/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "Bulbasaur", diff --git a/src/locales/it/save-slot-select-ui-handler.ts b/src/locales/it/save-slot-select-ui-handler.ts index a7485c842f2..d1825daeb1f 100644 --- a/src/locales/it/save-slot-select-ui-handler.ts +++ b/src/locales/it/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "Sovrascrivere i dati nello slot selezionato?", diff --git a/src/locales/it/settings.ts b/src/locales/it/settings.ts new file mode 100644 index 00000000000..ea70c2ec94b --- /dev/null +++ b/src/locales/it/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "Ragazzo", + "girl": "Ragazza", + "general": "General", + "display": "Display", + "audio": "Audio", + "gamepad": "Gamepad", + "keyboard": "Keyboard", + "gameSpeed": "Game Speed", + "hpBarSpeed": "HP Bar Speed", + "expGainsSpeed": "EXP Gains Speed", + "expPartyDisplay": "Show EXP Party", + "skipSeenDialogues": "Skip Seen Dialogues", + "battleStyle": "Battle Style", + "enableRetries": "Enable Retries", + "tutorials": "Tutorials", + "touchControls": "Touch Controls", + "vibrations": "Vibrations", + "normal": "Normal", + "fast": "Fast", + "faster": "Faster", + "skip": "Skip", + "levelUpNotifications": "Level Up Notifications", + "on": "On", + "off": "Off", + "switch": "Switch", + "set": "Set", + "auto": "Auto", + "disabled": "Disabled", + "language": "Language", + "change": "Change", + "uiTheme": "UI Theme", + "default": "Default", + "legacy": "Legacy", + "windowType": "Window Type", + "moneyFormat": "Money Format", + "damageNumbers": "Damage Numbers", + "simple": "Simple", + "fancy": "Fancy", + "abbreviated": "Abbreviated", + "moveAnimations": "Move Animations", + "showStatsOnLevelUp": "Show Stats on Level Up", + "candyUpgradeNotification": "Candy Upgrade Notification", + "passivesOnly": "Passives Only", + "candyUpgradeDisplay": "Candy Upgrade Display", + "icon": "Icon", + "animation": "Animation", + "moveInfo": "Move Info", + "showMovesetFlyout": "Show Moveset Flyout", + "showArenaFlyout": "Show Arena Flyout", + "showTimeOfDayWidget": "Show Time of Day Widget", + "timeOfDayAnimation": "Time of Day Animation", + "bounce": "Bounce", + "timeOfDay_back": "Back", + "spriteSet": "Sprite Set", + "consistent": "Consistent", + "mixedAnimated": "Mixed Animated", + "fusionPaletteSwaps": "Fusion Palette Swaps", + "playerGender": "Player Gender", + "typeHints": "Type Hints", + "masterVolume": "Master Volume", + "bgmVolume": "BGM Volume", + "seVolume": "SE Volume", + "musicPreference": "Music Preference", + "mixed": "Mixed", + "gamepadPleasePlug": "Please Plug in a Gamepad or Press a Button", + "delete": "Delete", + "keyboardPleasePress": "Please Press a Key on Your Keyboard", + "reset": "Reset", + "requireReload": "Reload Required", + "action": "Action", + "back": "Back", + "pressToBind": "Press to Bind", + "pressButton": "Press a Button...", + "buttonUp": "Up", + "buttonDown": "Down", + "buttonLeft": "Left", + "buttonRight": "Right", + "buttonAction": "Action", + "buttonMenu": "Menu", + "buttonSubmit": "Submit", + "buttonCancel": "Cancel", + "buttonStats": "Stats", + "buttonCycleForm": "Cycle Form", + "buttonCycleShiny": "Cycle Shiny", + "buttonCycleGender": "Cycle Gender", + "buttonCycleAbility": "Cycle Ability", + "buttonCycleNature": "Cycle Nature", + "buttonCycleVariant": "Cycle Variant", + "buttonSpeedUp": "Speed Up", + "buttonSlowDown": "Slow Down", + "alt": " (Alt)", + "mute": "Mute", + "controller": "Controller", + "gamepadSupport": "Gamepad Support" +} as const; diff --git a/src/locales/it/splash-messages.ts b/src/locales/it/splash-messages.ts index 6ad80f64e89..eeb71842094 100644 --- a/src/locales/it/splash-messages.ts +++ b/src/locales/it/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "Battaglie Vinte!", diff --git a/src/locales/it/starter-select-ui-handler.ts b/src/locales/it/starter-select-ui-handler.ts index 48a0badaefc..8f68e5ff10d 100644 --- a/src/locales/it/starter-select-ui-handler.ts +++ b/src/locales/it/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "addToParty": "Aggiungi al gruppo", "toggleIVs": "Vedi/Nascondi IV", "manageMoves": "Gestisci mosse", + "manageNature": "Gestisci natura", "useCandies": "Usa caramelle", + "selectNature": "Seleziona natura.", "selectMoveSwapOut": "Seleziona una mossa da scambiare.", "selectMoveSwapWith": "Seleziona una mossa da scambiare con", "unlockPassive": "Sblocca passiva", diff --git a/src/locales/it/trainers.ts b/src/locales/it/trainers.ts index dffac3bb9f4..420b9bf9f24 100644 --- a/src/locales/it/trainers.ts +++ b/src/locales/it/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/it/tutorial.ts b/src/locales/it/tutorial.ts index 8488fc3151f..1a746cf0db7 100644 --- a/src/locales/it/tutorial.ts +++ b/src/locales/it/tutorial.ts @@ -1,42 +1,42 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `Benvenuto in PokéRogue! Questo gioco si concentra sulle battaglie, con elementi roguelite. - $Questo gioco non è monetizzato e non siamo proprietari di Pokemon e Assets presenti nel gioco. - $Il gioco è work-in-progress ma giocabile al 100%.\nPer reportare eventuali bugs è possibile discuterne sul nostro Discord. - $Se il game risulta 'lento', assicurati di aver abilitato l'Accelerazione Hardware nelle impostazioni del tuo Browser`, + $Questo gioco non è monetizzato e non siamo proprietari di Pokémon ed assets presenti nel gioco. + $Il progetto è work-in-progress, ma giocabile al 100%.\nPer segnalare eventuali bug è possibile contattarci al nostro apposito Discord. + $Se il gioco risulta 'lento', assicurati di aver abilitato l'accelerazione hardware nelle impostazioni del tuo browser`, - "accessMenu": "Per accedere al menù, press M o Esc.\nDal menù puoi cambiare impostazioni, controllare la wiki e accedere a varie features.", + "accessMenu": "Per accedere al menu, premi M o esc.\nDal menu puoi modificare le impostazioni, controllare la wiki ed accedere a varie features.", - "menu": `Da questo menù puoi accedere alle impostazioni. - $Dalle impostazioni puoi cambiare velocità di gioco, stile di finestra e altre opzioni. - $Ci sono varie funzionalità, controlla bene e non perderti nulla!`, + "menu": `Da questo menu puoi accedere alle impostazioni. + $Esse ti permettono di cambiare velocità di gioco, stile delle finestre ed altre opzioni. + $Ci sono varie funzionalità: controlla bene e non perderti nulla!`, - "starterSelect": `Da questa schermata puoi selezionare il tuo starter.\nQuesti sono i membri iniziali del tuo parti. + "starterSelect": `Da questa schermata puoi selezionare il tuo starter.\nQuesti sono i membri iniziali della tua squadra. $Ogni starter ha un valore. Puoi avere fino a \n6 Pokèmon, avendo a disposizione un massimo di 10 punti. - $Puoi anche selezionare Sesso, Abilità, e Forma a seconda delle\nvarianti che hai catturato o schiuso. + $Puoi anche selezionare genere, abilità, e forma a seconda delle\nvarianti che hai catturato o schiuso. $Le IVs di una specie sono le migliori rispetto a tutte quelle che hai\ncatturato o schiuso, quindi prova a catturarne il piu possibile!`, - "pokerus": `Giornalmente 3 Starter casuali disponibili avranno il bordo viola. - $Se possiedi uno di questi starter,\nprova ad aggiungerlo al party. Ricorda di controllare le info!`, + "pokerus": `Giornalmente 3 starter casuali disponibili avranno il bordo viola. + $Se possiedi uno di questi starter,\nprova ad aggiungerlo alla squadra. Ricorda di controllarne le info!`, - "statChange": `I cambiamenti alle statistiche persistono fintanto che i tuoi pokèmon resteranno in campo. + "statChange": `I cambiamenti alle statistiche persistono fintanto che i tuoi pokèmon restano in campo. $I tuoi pokemon verranno richiamati quando incontrerai un allenatore o al cambiamento di bioma. $Puoi anche vedere i cambiamenti alle statistiche in corso tenendo premuto C o Shift`, - "selectItem": `Dopo ogni battaglia avrai disponibili tre item.\nPotrai prenderne solo uno. - $Questi spaziano tra consumabili, item tenuti da Pokèmon o con un effetto passivo permanente. - $La maggior parte degli Item non Consumabili possono stackare in diversi modi. - $Alcuni Item risulteranno disponibili solo se possono essere usati, come Item Evolutivi. - $Puoi anche passare un Item tenuto da un Pokèmon ad un altro attraverso l'opzione 'trasferisci strumento'. - $L'opzione 'trasferisci strumento' sarà disponibile solo dopo aver assegnato uno strumento ad un Pokèmon. - $Puoi acquistare consumabili con le monete, progredendo saranno poi disponibili ulteriori oggetti. - $Assicurati di fare un acquisto prima di selezionare un item casuale, poichè passerai subito alla lotta successiva.`, + "selectItem": `Dopo ogni battaglia potrai scegliere tra 3 oggetti.\nPotrai prenderne solo uno. + $Questi spaziano tra consumabili, oggetti tenuti da Pokèmon o con un effetto passivo permanente. + $La maggior parte degli oggetti non consumabili possono accumulare i loro effetti in diversi modi. + $Alcuni risulteranno inoltre disponibili solo se possono essere usati, come ad esempio gli oggetti evolutivi. + $Puoi anche passare un oggetto tenuto da un Pokèmon a un altro attraverso l'opzione 'trasferisci strumento'. + $Quest'ultima sarà disponibile solo dopo aver assegnato uno strumento ad un Pokèmon. + $Puoi acquistare consumabili con le monete; progredendo saranno poi disponibili ulteriori oggetti. + $Assicurati di fare un acquisto prima di selezionare un item casuale, poichè dopo aver fatto ciò passerai subito alla lotta successiva.`, - "eggGacha": `Da questa schermata, puoi riscattare i tuoi vouchers in cambio di\nuova Pokèmon. - $Le uova vanno schiuse e saranno sempre più vicine alla schiusura dopo\nogni battaglia. Le uova più rare impiegheranno più battaglie per la schiusura. - $I Pokémon schiusi non verranno aggiunti alla tua squadra, saranno\naggiunti ai tuoi starters. - $I Pokémon schiusi generalmente hanno IVs migliori rispetto ai\n Pokémon selvatici. - $Alcuni Pokémon possono essere ottenuti solo tramite uova. + "eggGacha": `Da questa schermata puoi riscattare i tuoi vouchers in cambio di\nuova Pokèmon. + $Le uova vanno schiuse, e saranno sempre più vicine alla schiusura dopo\nogni battaglia. Le uova più rare impiegheranno più battaglie per la schiusura. + $I Pokémon schiusi non verranno aggiunti alla tua squadra, ma saranno\ninvece aggiunti ai tuoi starters. + $I Pokémon schiusi hanno (generalmente) IVs migliori rispetto ai\n Pokémon selvatici. + $Inoltre, alcuni Pokémon possono essere ottenuti solo tramite uova. $Ci sono 3 diversi macchinari con differenti\nbonus, scegli quello che preferisci!`, } as const; diff --git a/src/locales/it/voucher.ts b/src/locales/it/voucher.ts index f2bcb8d723c..54e81dbc9d4 100644 --- a/src/locales/it/voucher.ts +++ b/src/locales/it/voucher.ts @@ -1,11 +1,11 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "Vouchers", - "eggVoucher": "Egg Voucher", - "eggVoucherPlus": "Egg Voucher Plus", - "eggVoucherPremium": "Egg Voucher Premium", - "eggVoucherGold": "Egg Voucher Gold", - "locked": "Locked", - "defeatTrainer": "Defeat {{trainerName}}" -} as const; + "eggVoucher": "Voucher uovo", + "eggVoucherPlus": "Voucher uovo plus", + "eggVoucherPremium": "Voucher uovo premium", + "eggVoucherGold": "Voucher uovo dorato", + "locked": "Bloccato", + "defeatTrainer": "Sconfiggi {{trainerName}}" +} as const; diff --git a/src/locales/it/weather.ts b/src/locales/it/weather.ts index ed5d41a80af..2d169421a38 100644 --- a/src/locales/it/weather.ts +++ b/src/locales/it/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/ko/ability-trigger.ts b/src/locales/ko/ability-trigger.ts index 3ce78178081..c6c29b5f200 100644 --- a/src/locales/ko/ability-trigger.ts +++ b/src/locales/ko/ability-trigger.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{pokemonName}}[[는]] {{abilityName}} 때문에\n반동 데미지를 받지 않는다!", diff --git a/src/locales/ko/ability.ts b/src/locales/ko/ability.ts index c254ea635d6..f11c1363924 100644 --- a/src/locales/ko/ability.ts +++ b/src/locales/ko/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; /** * 본가 게임과 텍스트가 다를 경우 주석으로 표시 diff --git a/src/locales/ko/achv.ts b/src/locales/ko/achv.ts index 295c4cf72a1..a4141da13d8 100644 --- a/src/locales/ko/achv.ts +++ b/src/locales/ko/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/ko/battle-message-ui-handler.ts b/src/locales/ko/battle-message-ui-handler.ts index 20266a063e5..fdd79044090 100644 --- a/src/locales/ko/battle-message-ui-handler.ts +++ b/src/locales/ko/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "최고", diff --git a/src/locales/ko/battle.ts b/src/locales/ko/battle.ts index d9774bf1c06..48f7339e9ce 100644 --- a/src/locales/ko/battle.ts +++ b/src/locales/ko/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}}[[가]] 나타났다.", @@ -62,12 +62,13 @@ export const battle: SimpleTranslationEntries = { "drainMessage": "{{pokemonName}}[[로]]부터\n체력을 흡수했다!", "regainHealth": "{{pokemonName}}[[는]]\n기력을 회복했다!", "fainted": "{{pokemonNameWithAffix}}[[는]] 쓰러졌다!", - "statRose": "상승했다", - "statSharplyRose": "약간 상승했다", - "statRoseDrastically": "대폭 상승했다", - "statWontGoAnyHigher": "더 이상 상승할 수 없다", - "statFell": "떨어졌다", - "statHarshlyFell": "약간 떨어졌다", - "statSeverelyFell": "대폭 떨어졌다", - "statWontGoAnyLower": "더 이상 떨어질 수 없다", + "statRose": "[[가]] 올라갔다!", + "statSharplyRose": "[[가]] 크게 올라갔다!", + "statRoseDrastically": "[[가]] 매우 크게 올라갔다!", + "statWontGoAnyHigher": "[[는]] 더 올라가지 않는다!", + "statFell": "[[가]] 떨어졌다!", + "statHarshlyFell": "[[가]] 크게 떨어졌다!", + "statSeverelyFell": "[[가]] 매우 크게 떨어졌다!", + "statWontGoAnyLower": "[[는]] 더 떨어지지 않는다!", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/ko/berry.ts b/src/locales/ko/berry.ts index bea5d9ee13c..722edf62c9a 100644 --- a/src/locales/ko/berry.ts +++ b/src/locales/ko/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/ko/biome.ts b/src/locales/ko/biome.ts index 60fb016df64..7167618d161 100644 --- a/src/locales/ko/biome.ts +++ b/src/locales/ko/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "기억할 수 없는 곳", diff --git a/src/locales/ko/challenges.ts b/src/locales/ko/challenges.ts index 3dad36fd8d1..64fa316b3bb 100644 --- a/src/locales/ko/challenges.ts +++ b/src/locales/ko/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "챌린지 조건 설정", diff --git a/src/locales/ko/command-ui-handler.ts b/src/locales/ko/command-ui-handler.ts index b10534cfb92..a40ec0316bf 100644 --- a/src/locales/ko/command-ui-handler.ts +++ b/src/locales/ko/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "싸운다", diff --git a/src/locales/ko/config.ts b/src/locales/ko/config.ts index ca14d87cc10..99cf5ddd8ea 100644 --- a/src/locales/ko/config.ts +++ b/src/locales/ko/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/ko/settings.js"; export const koConfig = { ability: ability, @@ -74,6 +75,7 @@ export const koConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/ko/dialogue.ts b/src/locales/ko/dialogue.ts index fc4530b94fa..9dcd6294e7c 100644 --- a/src/locales/ko/dialogue.ts +++ b/src/locales/ko/dialogue.ts @@ -1,4 +1,4 @@ -import { DialogueTranslationEntries, SimpleTranslationEntries } from "#app/plugins/i18n"; +import { DialogueTranslationEntries, SimpleTranslationEntries } from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) export const PGMdialogue: DialogueTranslationEntries = { @@ -860,19 +860,19 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "crasher_wake": { "encounter": { - 1: "Crash! Crash! Watch out!\nCrasher Wake…is…heeere!", - 2: "Crash! Crash! Crasher Wake!", - 3: "I'm the tidal wave of power to wash you away!" + 1: "철썩! 철썩! 조심해라!\n맥시멈 가면이…지금…간다!", + 2: "철썩! 철썩! 파도의 맥시멈 가면!", + 3: "밀물같은 힘으로 쓸려나가도록 해보실까!!" }, "victory": { - 1: "That puts a grin on my face!\nGuhahaha! That was a blast!", - 2: "Hunwah! It's gone and ended!\nHow will I say this…\nI want more! I wanted to battle a lot more!", - 3: "WHAAAAT!?" + 1: "저절로 웃음이 나오게 되는군!\n크하하핫! 정말 훌륭했다!", + 2: "우왓! 끝나버렸나!\n뭐랄까…\n좀 더 싸우고 싶은 기분이야!", + 3: "이럴수가!?" }, "defeat": { - 1: "Yeeeeah! That's right!", - 2: "I won, but I want more! I wanted to battle a lot more!", - 3: "So long!" + 1: "으하하핫! 보람차군!", + 2: "내가 이겼지만, 아쉽군! 좀 더 배틀하고 싶은데!", + 3: "잘 가게나!" } }, "falkner": { @@ -1164,19 +1164,19 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "candice": { "encounter": { - 1: `You want to challenge Candice? Sure thing! I was waiting for someone tough! - $But I should tell you, I'm tough because I know how to focus.`, - 2: `Pokémon, fashion, romance… It's all about focus! - $I'll show you just what I mean. Get ready to lose!` + 1: `나, 무청에게 도전하고 싶은거야? 좋아! 강한 사람을 기다리고 있었으니까! + $그치만 말해두는데, 집중하는 방법을 아는 나도 강력하거든.`, + 2: `포켓몬도 멋도 연애도 정신 집중이 중요하다고! + $무슨 뜻인지 보여줄테니까 각오해!` }, "victory": { - 1: "I must say, I'm warmed up to you! I might even admire you a little.", - 2: `Wow! You're great! You've earned my respect! - $I think your focus and will bowled us over totally. ` + 1: "있지, 나 조금 불타오르게 됐어! 널 조금 존경하게 될지도 몰라.", + 2: `우와! 제법인데! 내가 존경하게 만들다니! + $네 집중력과 의지, 완전히 나를 압도하는 같아. ` }, "defeat": { - 1: "I sensed your will to win, but I don't lose!", - 2: "See? Candice's focus! My Pokémon's focus is great, too!" + 1: "이기고자 하는 의지는 전해졌지만, 난 지지 않았어!", + 2: "봤지? 무청의 집중력! 내 포켓몬의 집중력도 대단하다구!" } }, "gardenia": { @@ -1192,13 +1192,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "aaron": { "encounter": { - 1: "Ok! Let me take you on!" + 1: "좋습니다! 그럼 상대해 드리죠!" }, "victory": { - 1: "Battling is a deep and complex affair…" + 1: "승부는 딥하고 컴플렉스한 일이네요…" }, "defeat": { - 1: "Victory over an Elite Four member doesn't come easily." + 1: "사천왕을 상대로 하는 승리는 쉽게 오지 않는다구요." } }, "cress": { @@ -1429,15 +1429,15 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "bertha": { "encounter": { - 1: "Well, would you show this old lady how much you've learned?" + 1: "그럼, 할머니가 네가 얼마나 해낼 수 있는지 보도록 할게?" }, "victory": { - 1: `Well! Dear child, I must say, that was most impressive. - $Your Pokémon believed in you and did their best to earn you the win. - $Even though I've lost, I find myself with this silly grin!`, + 1: `좋아! 꼬마야, 정말로, 인상적이었단다. + $Y네 포켓몬은 너를 믿고 승리를 위해 최선을 다했구나. + $비록 내가 졌지만, 좋아서 바보같이 웃음이 나오는구나!`, }, "defeat": { - 1: "Hahahahah! Looks like this old lady won!" + 1: "호호호! 이 할머니가 이겼구나!" } }, "lenora": { @@ -1510,13 +1510,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "flint": { "encounter": { - 1: "Hope you're warmed up, cause here comes the Big Bang!" + 1: "뜨겁게 타오를 준비는 됐겠지, 이제 곧 대폭발이 다가올테니까!" }, "victory": { - 1: "Incredible! Your moves are so hot, they make mine look lukewarm!" + 1: "놀랍군! 네 기술이 너무 뜨거워서, 내가 미적지근해보이잖아!" }, "defeat": { - 1: "Huh? Is that it? I think you need a bit more passion." + 1: "하? 그게 다야? 좀 더 열정이 필요해보이는걸." } }, "grimsley": { @@ -1638,16 +1638,16 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "lucian": { "encounter": { - 1: `Just a moment, please. The book I'm reading has nearly reached its thrilling climax… - $The hero has obtained a mystic sword and is about to face their final trial… Ah, never mind. - $Since you've made it this far, I'll put that aside and battle you. - $Let me see if you'll achieve as much glory as the hero of my book!,` + 1: `잠깐, 기다려주세요. 제가 읽던 책이 거의 클라이맥스에 도달했거든요… + $주인공이 성스러운 검을 얻었고 마지막 시련을 앞두고 있는데… 아, 신경 쓰지 마세요. + $여기까지 왔으니, 그건 제쳐두고 당신과 싸워야겠습니다. + $당신이 과연 주인공이 될 그릇인지 확인해 보도록 하죠!` }, "victory": { - 1: "I see… It appears you've put me in checkmate." + 1: "그렇군요… 결국 체크메이트인가요." }, "defeat": { - 1: "I have a reputation to uphold." + 1: "제 평판을 지켜냈네요." } }, "drasna": { @@ -1757,13 +1757,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "cynthia": { "encounter": { - 1: "I, Cynthia, accept your challenge! There won't be any letup from me!" + 1: "나, 난천은, 네 도전을 받아들일게! 온 힘을 다해 너와 시합하겠어!" }, "victory": { - 1: "No matter how fun the battle is, it will always end sometime…" + 1: "포켓몬 배틀보다 재밌는 것은 없지만, 언젠간 끝나기 마련이니…" }, "defeat": { - 1: "Even if you lose, never lose your love of Pokémon." + 1: "비록 졌어도, 포켓몬에 대한 사랑은 잃지 않도록 해." } }, "iris": { @@ -1911,15 +1911,15 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "byron": { "encounter": { - 1: `Trainer! You're young, just like my son, Roark. - $With more young Trainers taking charge, the future of Pokémon is bright! - $So, as a wall for young people, I'll take your challenge!`, + 1: `젊은 트레이너여! 자네는 내 아들 강석처럼 젊군. + $젊은 트레이너가 많아질수록, 포켓몬의 미래도 밝지! + $그러니, 젊은이들이 넘어야할 벽으로서 상대해주겠다!`, }, "victory": { - 1: "Hmm! My sturdy Pokémon--defeated!" + 1: "흠! 내 견고한 포켓몬이--져버렸군!" }, "defeat": { - 1: "Gwahahaha! How were my sturdy Pokémon?!" + 1: "으하하핫! 내 견고한 포켓몬은 어땠나?!" } }, "olympia": { @@ -1935,17 +1935,17 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "volkner": { "encounter": { - 1: `Since you've come this far, you must be quite strong… - $I hope you're the Trainer who'll make me remember how fun it is to battle!`, + 1: `여기까지 왔으니, 넌 꽤 강하겠군… + $네가 내게 포켓몬 승부의 즐거움을 상기시켜 줄 트레이너이길 바란다!`, }, "victory": { - 1: `You've got me beat… - $Your desire and the noble way your Pokémon battled for you… - $I even felt thrilled during our match. That was a very good battle.`, + 1: `너 나를 이겼군… + $네 열정과 포켓몬이 그런 너를 위해 싸워준 고귀한 방식… + $심지어 스릴까지 넘쳤다. 아주 좋은 승부였어.`, }, "defeat": { - 1: `It was not shocking at all… - $That is not what I wanted!`, + 1: `전혀 충격적이지 않았다… + $이런 건 원하지 않았어!`, } }, "burgh": { @@ -2289,28 +2289,28 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "alder": { "encounter": { - 1: "Prepare yourself for a match against the strongest Trainer in Unova!" + 1: "하나지방에서 가장 강한 트레이너를 상대할 준비는 됐나?" }, "victory": { - 1: "Well done! You certainly are an unmatched talent." + 1: "장하구나! 실로 견줄 자가 천하에 없도다!" }, "defeat": { - 1: `A fresh wind blows through my heart... - $What an extraordinary effort!` + 1: `나의 마음에 상쾌한 바람이 지나갔다... + $정말 대단한 노력이다!` } }, "kieran": { "encounter": { - 1: `Through hard work, I become stronger and stronger! - $I don't lose.` + 1: `난 노력을 통해 강해지고 또 강해지지! + $난 지지 않아.` }, "victory": { - 1: `I don't believe it... - $What a fun and heart-pounding battle!` + 1: `믿을 수 없어... + $정말 재밌고 가슴 뛰는 배틀이었어!` }, "defeat": { - 1: `Wowzers, what a battle! - $Time for you to train even harder.` + 1: `세상에 마상에! 정말 멋진 배틀이었어! + $네가 더 열심히 훈련할 시간이야.` } }, "rival": { diff --git a/src/locales/ko/egg.ts b/src/locales/ko/egg.ts index abb1f3ceadf..3c2d1447c44 100644 --- a/src/locales/ko/egg.ts +++ b/src/locales/ko/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "알", diff --git a/src/locales/ko/fight-ui-handler.ts b/src/locales/ko/fight-ui-handler.ts index 6ce47e759fe..cf840cc4495 100644 --- a/src/locales/ko/fight-ui-handler.ts +++ b/src/locales/ko/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", diff --git a/src/locales/ko/game-mode.ts b/src/locales/ko/game-mode.ts index ad387010a8f..e85a9bb232b 100644 --- a/src/locales/ko/game-mode.ts +++ b/src/locales/ko/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "클래식", diff --git a/src/locales/ko/game-stats-ui-handler.ts b/src/locales/ko/game-stats-ui-handler.ts index c408e480b85..d21f1b2acda 100644 --- a/src/locales/ko/game-stats-ui-handler.ts +++ b/src/locales/ko/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "통계", diff --git a/src/locales/ko/growth.ts b/src/locales/ko/growth.ts index 72dbfcde934..941198fd5d4 100644 --- a/src/locales/ko/growth.ts +++ b/src/locales/ko/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "불규칙", diff --git a/src/locales/ko/menu-ui-handler.ts b/src/locales/ko/menu-ui-handler.ts index efca85d3e48..5e13d010438 100644 --- a/src/locales/ko/menu-ui-handler.ts +++ b/src/locales/ko/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "게임 설정", diff --git a/src/locales/ko/menu.ts b/src/locales/ko/menu.ts index 9245d67533a..134963d6cce 100644 --- a/src/locales/ko/menu.ts +++ b/src/locales/ko/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,8 +34,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "세션 불러오기 성공.", "failedToLoadSession": "세션을 불러올 수 없었습니다.\n파일이 손상되었을 수 있습니다.", "boyOrGirl": "너는 남자니?\n아니면 여자니?", - "boy": "남자", - "girl": "여자", "evolving": "…오잉!?\n{{pokemonName}}의 모습이…!", "stoppedEvolving": "얼라리…?\n{{pokemonName}}의 변화가 멈췄다!", "pauseEvolutionsQuestion": "{{pokemonName}}[[를]] 진화하지 않게 만드시겠습니까?\n포켓몬 화면에서 다시 활성화시킬 수 있습니다.", @@ -44,6 +42,10 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "일간 랭킹", "weeklyRankings": "주간 랭킹", "noRankings": "랭킹 정보 없음", + "positionIcon": "#", + "usernameScoreboard": "이름", + "score": "점수", + "wave": "웨이브", "loading": "로딩 중…", "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "플레이어 온라인", diff --git a/src/locales/ko/modifier-type.ts b/src/locales/ko/modifier-type.ts index 29b4cd08f32..479e1ca02e2 100644 --- a/src/locales/ko/modifier-type.ts +++ b/src/locales/ko/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/ko/move.ts b/src/locales/ko/move.ts index a40625893ac..ae1bbf088e3 100644 --- a/src/locales/ko/move.ts +++ b/src/locales/ko/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; /** * 본가 게임과 텍스트가 다르거나 번역문을 완전히 확인하지 못한 경우 주석으로 표시 diff --git a/src/locales/ko/nature.ts b/src/locales/ko/nature.ts index 3581f2a7c94..2d7e2ec85f4 100644 --- a/src/locales/ko/nature.ts +++ b/src/locales/ko/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "노력", diff --git a/src/locales/ko/party-ui-handler.ts b/src/locales/ko/party-ui-handler.ts index ce731e4915f..15a42ae0521 100644 --- a/src/locales/ko/party-ui-handler.ts +++ b/src/locales/ko/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "SEND_OUT": "교체한다", diff --git a/src/locales/ko/pokeball.ts b/src/locales/ko/pokeball.ts index 123df79ea93..195ae3a3594 100644 --- a/src/locales/ko/pokeball.ts +++ b/src/locales/ko/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "몬스터볼", diff --git a/src/locales/ko/pokemon-info-container.ts b/src/locales/ko/pokemon-info-container.ts index c1477ffc08b..31048dee3ef 100644 --- a/src/locales/ko/pokemon-info-container.ts +++ b/src/locales/ko/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "기술", diff --git a/src/locales/ko/pokemon-info.ts b/src/locales/ko/pokemon-info.ts index 29041d5b20e..89d1742f437 100644 --- a/src/locales/ko/pokemon-info.ts +++ b/src/locales/ko/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { diff --git a/src/locales/ko/pokemon.ts b/src/locales/ko/pokemon.ts index d0ef9c3923c..68eae6b9ca6 100644 --- a/src/locales/ko/pokemon.ts +++ b/src/locales/ko/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "이상해씨", diff --git a/src/locales/ko/save-slot-select-ui-handler.ts b/src/locales/ko/save-slot-select-ui-handler.ts index 213da34bda5..29f77cd325f 100644 --- a/src/locales/ko/save-slot-select-ui-handler.ts +++ b/src/locales/ko/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "선택한 슬롯에 데이터를 덮어쓰시겠습니까?", diff --git a/src/locales/ko/settings.ts b/src/locales/ko/settings.ts new file mode 100644 index 00000000000..08f0c635199 --- /dev/null +++ b/src/locales/ko/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "남자", + "girl": "여자", + "general": "일반", + "display": "디스플레이", + "audio": "오디오", + "gamepad": "게임패드", + "keyboard": "키보드", + "gameSpeed": "게임 속도", + "hpBarSpeed": "HP 바 속도", + "expGainsSpeed": "경험치 획득 속도", + "expPartyDisplay": "파티 경험치 표시", + "skipSeenDialogues": "본 대화 생략", + "battleStyle": "시합 룰", + "enableRetries": "재도전 허용", + "tutorials": "튜토리얼", + "touchControls": "터치 컨트롤", + "vibrations": "진동", + "normal": "보통", + "fast": "빠르게", + "faster": "더 빠르게", + "skip": "스킵", + "levelUpNotifications": "레벨업 알림", + "on": "설정", + "off": "해제", + "switch": "교체", + "set": "토너먼트", + "auto": "자동", + "disabled": "비활성", + "language": "언어", + "change": "변경", + "uiTheme": "UI 테마", + "default": "기본", + "legacy": "레거시", + "windowType": "윈도우 타입", + "moneyFormat": "소지금 표시", + "damageNumbers": "대미지 숫자 표시", + "simple": "심플", + "fancy": "팬시", + "abbreviated": "축약", + "moveAnimations": "배틀 애니메이션", + "showStatsOnLevelUp": "레벨업 능력치 표시", + "candyUpgradeNotification": "사탕 업그레이드 알림", + "passivesOnly": "패시브만", + "candyUpgradeDisplay": "사탕 업그레이드 표시", + "icon": "아이콘", + "animation": "애니메이션", + "moveInfo": "기술 정보", + "showMovesetFlyout": "상대 기술 보기", + "showArenaFlyout": "배틀 효과 보기", + "showTimeOfDayWidget": "시간 위젯", + "timeOfDayAnimation": "시간 애니메이션", + "bounce": "흔들림", + "timeOfDay_back": "고정", + "spriteSet": "스프라이트 표시", + "consistent": "기본", + "mixedAnimated": "믹스", + "fusionPaletteSwaps": "셰이더 적용", + "playerGender": "플레이어 성별", + "typeHints": "상성 힌트", + "masterVolume": "마스터 볼륨", + "bgmVolume": "BGM 볼륨", + "seVolume": "SE 볼륨", + "musicPreference": "음악 설정", + "mixed": "믹스", + "gamepadPleasePlug": "게임패드를 연결하거나 버튼을 입력하세요", + "delete": "삭제", + "keyboardPleasePress": "키보드의 키를 입력하세요", + "reset": "리셋", + "requireReload": "새로고침 필요", + "action": "액션", + "back": "고정", + "pressToBind": "할당을 위해 입력하세요", + "pressButton": "버튼을 입력하세요", + "buttonUp": "위", + "buttonDown": "아래", + "buttonLeft": "왼쪽", + "buttonRight": "오른쪽", + "buttonAction": "액션", + "buttonMenu": "메뉴", + "buttonSubmit": "확인", + "buttonCancel": "취소", + "buttonStats": "스탯", + "buttonCycleForm": "폼 변환", + "buttonCycleShiny": "특별한 색 변환", + "buttonCycleGender": "성별 변환", + "buttonCycleAbility": "특성 변환", + "buttonCycleNature": "성격 변환", + "buttonCycleVariant": "색상 변환", + "buttonSpeedUp": "속도 올리기", + "buttonSlowDown": "속도 내리기", + "alt": " (대체)", + "mute": "Mute", + "controller": "Controller", + "gamepadSupport": "Gamepad Support" +} as const; diff --git a/src/locales/ko/splash-messages.ts b/src/locales/ko/splash-messages.ts index 33006370b93..b875e7b282f 100644 --- a/src/locales/ko/splash-messages.ts +++ b/src/locales/ko/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "전투에서 승리하세요!", diff --git a/src/locales/ko/starter-select-ui-handler.ts b/src/locales/ko/starter-select-ui-handler.ts index 587baa3abc4..ab155a4a048 100644 --- a/src/locales/ko/starter-select-ui-handler.ts +++ b/src/locales/ko/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's diff --git a/src/locales/ko/trainers.ts b/src/locales/ko/trainers.ts index 2a61627c5a7..374b0180364 100644 --- a/src/locales/ko/trainers.ts +++ b/src/locales/ko/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/ko/tutorial.ts b/src/locales/ko/tutorial.ts index 1e0f8af3ce1..834f1be6345 100644 --- a/src/locales/ko/tutorial.ts +++ b/src/locales/ko/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { intro: `포켓로그에 오신 것을 환영합니다! 로그라이트 요소가 가미된 전투 중심의 포켓몬 팬게임입니다. diff --git a/src/locales/ko/voucher.ts b/src/locales/ko/voucher.ts index df9e6b31728..dd63977a218 100644 --- a/src/locales/ko/voucher.ts +++ b/src/locales/ko/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "바우처", diff --git a/src/locales/ko/weather.ts b/src/locales/ko/weather.ts index 81340d9567a..7fbd1eaf20b 100644 --- a/src/locales/ko/weather.ts +++ b/src/locales/ko/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/pt_BR/ability-trigger.ts b/src/locales/pt_BR/ability-trigger.ts index 98f83ac720b..766243c7d7e 100644 --- a/src/locales/pt_BR/ability-trigger.ts +++ b/src/locales/pt_BR/ability-trigger.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!", diff --git a/src/locales/pt_BR/ability.ts b/src/locales/pt_BR/ability.ts index 48e8790b227..05592f3fe1e 100644 --- a/src/locales/pt_BR/ability.ts +++ b/src/locales/pt_BR/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { stench: { diff --git a/src/locales/pt_BR/achv.ts b/src/locales/pt_BR/achv.ts index ccf8078071d..ea77e0c17e9 100644 --- a/src/locales/pt_BR/achv.ts +++ b/src/locales/pt_BR/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/pt_BR/battle-message-ui-handler.ts b/src/locales/pt_BR/battle-message-ui-handler.ts index b0d5d17e496..a7b0fb1f13b 100644 --- a/src/locales/pt_BR/battle-message-ui-handler.ts +++ b/src/locales/pt_BR/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "Perfeito", diff --git a/src/locales/pt_BR/battle.ts b/src/locales/pt_BR/battle.ts index 72d97f9f1cf..036c761bca7 100644 --- a/src/locales/pt_BR/battle.ts +++ b/src/locales/pt_BR/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} apareceu.", @@ -70,4 +70,5 @@ export const battle: SimpleTranslationEntries = { "statHarshlyFell": "diminuiu duramente", "statSeverelyFell": "diminuiu severamente", "statWontGoAnyLower": "não vai mais diminuir", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/pt_BR/berry.ts b/src/locales/pt_BR/berry.ts index e36d0b0f180..d409565168f 100644 --- a/src/locales/pt_BR/berry.ts +++ b/src/locales/pt_BR/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/pt_BR/biome.ts b/src/locales/pt_BR/biome.ts index 6ba9c7e47f1..46dad06b0de 100644 --- a/src/locales/pt_BR/biome.ts +++ b/src/locales/pt_BR/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "Em algum lugar do qual você não se lembra", diff --git a/src/locales/pt_BR/challenges.ts b/src/locales/pt_BR/challenges.ts index 9b7bfe1973c..98731fe890b 100644 --- a/src/locales/pt_BR/challenges.ts +++ b/src/locales/pt_BR/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "Desafios", diff --git a/src/locales/pt_BR/command-ui-handler.ts b/src/locales/pt_BR/command-ui-handler.ts index 2ad14e4ae94..cd8f7c4a378 100644 --- a/src/locales/pt_BR/command-ui-handler.ts +++ b/src/locales/pt_BR/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "Lutar", diff --git a/src/locales/pt_BR/config.ts b/src/locales/pt_BR/config.ts index fd35076a8f1..8d34c1539ef 100644 --- a/src/locales/pt_BR/config.ts +++ b/src/locales/pt_BR/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/pt_BR/settings.js"; export const ptBrConfig = { ability: ability, @@ -75,6 +76,7 @@ export const ptBrConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/pt_BR/dialogue.ts b/src/locales/pt_BR/dialogue.ts index 8d1e13d3177..a566192fef5 100644 --- a/src/locales/pt_BR/dialogue.ts +++ b/src/locales/pt_BR/dialogue.ts @@ -1,4 +1,4 @@ -import { DialogueTranslationEntries, SimpleTranslationEntries } from "#app/plugins/i18n"; +import { DialogueTranslationEntries, SimpleTranslationEntries } from "#app/interfaces/locales"; // Diálogo dos NPCs no jogo quando o personagem do jogador é masculino (ou não definido) export const PGMdialogue: DialogueTranslationEntries = { diff --git a/src/locales/pt_BR/egg.ts b/src/locales/pt_BR/egg.ts index 996ab85d8c5..112e5c61240 100644 --- a/src/locales/pt_BR/egg.ts +++ b/src/locales/pt_BR/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "Ovo", diff --git a/src/locales/pt_BR/fight-ui-handler.ts b/src/locales/pt_BR/fight-ui-handler.ts index a8e5d3c3cda..6ce615ad5b1 100644 --- a/src/locales/pt_BR/fight-ui-handler.ts +++ b/src/locales/pt_BR/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", diff --git a/src/locales/pt_BR/game-mode.ts b/src/locales/pt_BR/game-mode.ts index 5f0e930703b..44396635c6c 100644 --- a/src/locales/pt_BR/game-mode.ts +++ b/src/locales/pt_BR/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "Clássico", diff --git a/src/locales/pt_BR/game-stats-ui-handler.ts b/src/locales/pt_BR/game-stats-ui-handler.ts index 396b30b4c78..863f9e773f6 100644 --- a/src/locales/pt_BR/game-stats-ui-handler.ts +++ b/src/locales/pt_BR/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "Estatísticas", diff --git a/src/locales/pt_BR/growth.ts b/src/locales/pt_BR/growth.ts index 945520c91d7..7b268ae49ef 100644 --- a/src/locales/pt_BR/growth.ts +++ b/src/locales/pt_BR/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "Muito Rápido", diff --git a/src/locales/pt_BR/menu-ui-handler.ts b/src/locales/pt_BR/menu-ui-handler.ts index 8e6fc83eb36..47386943831 100644 --- a/src/locales/pt_BR/menu-ui-handler.ts +++ b/src/locales/pt_BR/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "Configurações", diff --git a/src/locales/pt_BR/menu.ts b/src/locales/pt_BR/menu.ts index f4fc8cc3a72..7490ea64ba8 100644 --- a/src/locales/pt_BR/menu.ts +++ b/src/locales/pt_BR/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,8 +34,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "Sessão carregada com sucesso.", "failedToLoadSession": "Não foi possível carregar os dados da sua sessão.\nEles podem estar corrompidos.", "boyOrGirl": "Você é um menino ou uma menina?", - "boy": "Menino", - "girl": "Menina", "evolving": "Que?\n{{pokemonName}} tá evoluindo!", "stoppedEvolving": "{{pokemonName}} parou de evoluir.", "pauseEvolutionsQuestion": "Gostaria de pausar evoluções para {{pokemonName}}?\nEvoluções podem ser religadas na tela de equipe.", @@ -44,11 +42,15 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "Classificação Diária", "weeklyRankings": "Classificação Semanal", "noRankings": "Sem Classificação", + "positionIcon": "#", + "usernameScoreboard": "Usuário", + "score": "Pontuação", + "wave": "Onda", "loading": "Carregando…", "loadingAsset": "Carregando recurso: {{assetName}}", "playersOnline": "Jogadores Ativos", "yes": "Sim", "no": "Não", "disclaimer": "AVISO", - "disclaimerDescription": "Este jogo é um produto inacabado; ele pode ter problemas de jogabilidade (incluindo possíveis perdas de dados salvos),\n sofrer alterações sem aviso prévio e pode ou não ser atualizado ou concluído." + "disclaimerDescription": "Este jogo é um produto inacabado; ele pode ter problemas de jogabilidade (incluindo possíveis perdas de dados salvos),\n sofrer alterações sem aviso prévio e pode ou não ser atualizado ou concluído.", } as const; diff --git a/src/locales/pt_BR/modifier-type.ts b/src/locales/pt_BR/modifier-type.ts index a0033434a3d..b63d237a4ee 100644 --- a/src/locales/pt_BR/modifier-type.ts +++ b/src/locales/pt_BR/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/pt_BR/move.ts b/src/locales/pt_BR/move.ts index 98d5c6a562e..233ec62fa06 100644 --- a/src/locales/pt_BR/move.ts +++ b/src/locales/pt_BR/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { "pound": { diff --git a/src/locales/pt_BR/nature.ts b/src/locales/pt_BR/nature.ts index 47f2f5f0930..976778bd1cb 100644 --- a/src/locales/pt_BR/nature.ts +++ b/src/locales/pt_BR/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "Destemida", diff --git a/src/locales/pt_BR/party-ui-handler.ts b/src/locales/pt_BR/party-ui-handler.ts index 763d733f3e8..683dc4b368a 100644 --- a/src/locales/pt_BR/party-ui-handler.ts +++ b/src/locales/pt_BR/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "SEND_OUT": "Trocar", diff --git a/src/locales/pt_BR/pokeball.ts b/src/locales/pt_BR/pokeball.ts index d7c5656fe5c..ee29b9612e6 100644 --- a/src/locales/pt_BR/pokeball.ts +++ b/src/locales/pt_BR/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "Poké Bola", diff --git a/src/locales/pt_BR/pokemon-info-container.ts b/src/locales/pt_BR/pokemon-info-container.ts index 2ee774888da..31b93d90daf 100644 --- a/src/locales/pt_BR/pokemon-info-container.ts +++ b/src/locales/pt_BR/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "Movimentos", diff --git a/src/locales/pt_BR/pokemon-info.ts b/src/locales/pt_BR/pokemon-info.ts index 8b37e6e1f74..a4af3f3e34a 100644 --- a/src/locales/pt_BR/pokemon-info.ts +++ b/src/locales/pt_BR/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { diff --git a/src/locales/pt_BR/pokemon.ts b/src/locales/pt_BR/pokemon.ts index 663c0f2163d..b3151eabb29 100644 --- a/src/locales/pt_BR/pokemon.ts +++ b/src/locales/pt_BR/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "Bulbasaur", diff --git a/src/locales/pt_BR/save-slot-select-ui-handler.ts b/src/locales/pt_BR/save-slot-select-ui-handler.ts index 23aeed7c5c7..6dee8a1a16a 100644 --- a/src/locales/pt_BR/save-slot-select-ui-handler.ts +++ b/src/locales/pt_BR/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "Substituir os dados desse slot?", diff --git a/src/locales/pt_BR/settings.ts b/src/locales/pt_BR/settings.ts new file mode 100644 index 00000000000..873d4ffd4a8 --- /dev/null +++ b/src/locales/pt_BR/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "Menino", + "girl": "Menina", + "general": "General", + "display": "Display", + "audio": "Audio", + "gamepad": "Gamepad", + "keyboard": "Keyboard", + "gameSpeed": "Game Speed", + "hpBarSpeed": "HP Bar Speed", + "expGainsSpeed": "EXP Gains Speed", + "expPartyDisplay": "Show EXP Party", + "skipSeenDialogues": "Skip Seen Dialogues", + "battleStyle": "Battle Style", + "enableRetries": "Enable Retries", + "tutorials": "Tutorials", + "touchControls": "Touch Controls", + "vibrations": "Vibrations", + "normal": "Normal", + "fast": "Fast", + "faster": "Faster", + "skip": "Skip", + "levelUpNotifications": "Level Up Notifications", + "on": "On", + "off": "Off", + "switch": "Switch", + "set": "Set", + "auto": "Auto", + "disabled": "Disabled", + "language": "Language", + "change": "Change", + "uiTheme": "UI Theme", + "default": "Default", + "legacy": "Legacy", + "windowType": "Window Type", + "moneyFormat": "Money Format", + "damageNumbers": "Damage Numbers", + "simple": "Simple", + "fancy": "Fancy", + "abbreviated": "Abbreviated", + "moveAnimations": "Move Animations", + "showStatsOnLevelUp": "Show Stats on Level Up", + "candyUpgradeNotification": "Candy Upgrade Notification", + "passivesOnly": "Passives Only", + "candyUpgradeDisplay": "Candy Upgrade Display", + "icon": "Icon", + "animation": "Animation", + "moveInfo": "Move Info", + "showMovesetFlyout": "Show Moveset Flyout", + "showArenaFlyout": "Show Arena Flyout", + "showTimeOfDayWidget": "Show Time of Day Widget", + "timeOfDayAnimation": "Time of Day Animation", + "bounce": "Bounce", + "timeOfDay_back": "Back", + "spriteSet": "Sprite Set", + "consistent": "Consistent", + "mixedAnimated": "Mixed Animated", + "fusionPaletteSwaps": "Fusion Palette Swaps", + "playerGender": "Player Gender", + "typeHints": "Type Hints", + "masterVolume": "Master Volume", + "bgmVolume": "BGM Volume", + "seVolume": "SE Volume", + "musicPreference": "Music Preference", + "mixed": "Mixed", + "gamepadPleasePlug": "Please Plug in a Gamepad or Press a Button", + "delete": "Delete", + "keyboardPleasePress": "Please Press a Key on Your Keyboard", + "reset": "Reset", + "requireReload": "Reload Required", + "action": "Action", + "back": "Back", + "pressToBind": "Press to Bind", + "pressButton": "Press a Button...", + "buttonUp": "Up", + "buttonDown": "Down", + "buttonLeft": "Left", + "buttonRight": "Right", + "buttonAction": "Action", + "buttonMenu": "Menu", + "buttonSubmit": "Submit", + "buttonCancel": "Cancel", + "buttonStats": "Stats", + "buttonCycleForm": "Cycle Form", + "buttonCycleShiny": "Cycle Shiny", + "buttonCycleGender": "Cycle Gender", + "buttonCycleAbility": "Cycle Ability", + "buttonCycleNature": "Cycle Nature", + "buttonCycleVariant": "Cycle Variant", + "buttonSpeedUp": "Speed Up", + "buttonSlowDown": "Slow Down", + "alt": " (Alt)", + "mute": "Mute", + "controller": "Controller", + "gamepadSupport": "Gamepad Support" +} as const; diff --git a/src/locales/pt_BR/splash-messages.ts b/src/locales/pt_BR/splash-messages.ts index 498b64d1e01..d21945943a0 100644 --- a/src/locales/pt_BR/splash-messages.ts +++ b/src/locales/pt_BR/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "Batalhas Ganhas!", diff --git a/src/locales/pt_BR/starter-select-ui-handler.ts b/src/locales/pt_BR/starter-select-ui-handler.ts index fc98e72c614..64a2ceff7c3 100644 --- a/src/locales/pt_BR/starter-select-ui-handler.ts +++ b/src/locales/pt_BR/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "addToParty": "Adicionar à equipe", "toggleIVs": "Mostrar IVs", "manageMoves": "Mudar Movimentos", + "manageNature": "Mudar Natureza", "useCandies": "Usar Doces", + "selectNature": "Escolha uma natureza.", "selectMoveSwapOut": "Escolha um movimento para substituir.", "selectMoveSwapWith": "Escolha o movimento que substituirá", "unlockPassive": "Aprender Passiva", diff --git a/src/locales/pt_BR/trainers.ts b/src/locales/pt_BR/trainers.ts index 9ada154e3a5..57fbe220412 100644 --- a/src/locales/pt_BR/trainers.ts +++ b/src/locales/pt_BR/trainers.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/pt_BR/tutorial.ts b/src/locales/pt_BR/tutorial.ts index bc0c5610e60..a64a7458881 100644 --- a/src/locales/pt_BR/tutorial.ts +++ b/src/locales/pt_BR/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `Bem-vindo ao PokéRogue! Este é um jogo Pokémon feito por fãs focado em batalhas com elementos roguelite. diff --git a/src/locales/pt_BR/voucher.ts b/src/locales/pt_BR/voucher.ts index 6ffffd48735..8c115caa810 100644 --- a/src/locales/pt_BR/voucher.ts +++ b/src/locales/pt_BR/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "Vouchers", diff --git a/src/locales/pt_BR/weather.ts b/src/locales/pt_BR/weather.ts index 07854512fdc..6aaab6d3cd9 100644 --- a/src/locales/pt_BR/weather.ts +++ b/src/locales/pt_BR/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/zh_CN/ability-trigger.ts b/src/locales/zh_CN/ability-trigger.ts index 07fedd8ac3e..908b3aaf258 100644 --- a/src/locales/zh_CN/ability-trigger.ts +++ b/src/locales/zh_CN/ability-trigger.ts @@ -1,8 +1,8 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!", - "badDreams": "{{pokemonName}} 被折磨着!", + "badDreams": "{{pokemonName}} 被折磨着!", "windPowerCharged": "受 {{moveName}} 的影响, {{pokemonName}} 提升了能力!", - "iceFaceAvoidedDamage": "{{pokemonName}} avoided\ndamage with {{abilityName}}!" + "iceFaceAvoidedDamage": "{{pokemonName}} 因为 {{abilityName}}\n避免了伤害!" } as const; diff --git a/src/locales/zh_CN/ability.ts b/src/locales/zh_CN/ability.ts index 77034d61743..9fe6b41ae31 100644 --- a/src/locales/zh_CN/ability.ts +++ b/src/locales/zh_CN/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { stench: { diff --git a/src/locales/zh_CN/achv.ts b/src/locales/zh_CN/achv.ts index 10012592330..63ccc97058a 100644 --- a/src/locales/zh_CN/achv.ts +++ b/src/locales/zh_CN/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/zh_CN/battle-message-ui-handler.ts b/src/locales/zh_CN/battle-message-ui-handler.ts index 89be345c32f..fb6e74cf66b 100644 --- a/src/locales/zh_CN/battle-message-ui-handler.ts +++ b/src/locales/zh_CN/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "最棒", @@ -7,4 +7,4 @@ export const battleMessageUiHandler: SimpleTranslationEntries = { "ivPrettyGood": "相当好", "ivDecent": "一般般", "ivNoGood": "也许不行", -} as const; +} as const; diff --git a/src/locales/zh_CN/battle.ts b/src/locales/zh_CN/battle.ts index 6d911b7b502..4b2b881f6b2 100644 --- a/src/locales/zh_CN/battle.ts +++ b/src/locales/zh_CN/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} 出现了。", @@ -56,18 +56,19 @@ export const battle: SimpleTranslationEntries = { "skipItemQuestion": "你确定要跳过拾取道具吗?", "eggHatching": "咦?", "ivScannerUseQuestion": "对 {{pokemonName}} 使用个体值扫描仪?", - "wildPokemonWithAffix": "Wild {{pokemonName}}", - "foePokemonWithAffix": "Foe {{pokemonName}}", - "useMove": "{{pokemonNameWithAffix}} used {{moveName}}!", - "drainMessage": "{{pokemonName}} had its\nenergy drained!", - "regainHealth": "{{pokemonName}} regained\nhealth!", - "fainted": "{{pokemonNameWithAffix}} fainted!", - "statRose": "rose", - "statSharplyRose": "sharply rose", - "statRoseDrastically": "rose drastically", - "statWontGoAnyHigher": "won't go any higher", - "statFell": "fell", - "statHarshlyFell": "harshly fell", - "statSeverelyFell": "severely fell", - "statWontGoAnyLower": "won't go any lower", + "wildPokemonWithAffix": "野生的 {{pokemonName}}", + "foePokemonWithAffix": "对手 {{pokemonName}}", + "useMove": "{{pokemonNameWithAffix}} 使用了 {{moveName}}!", + "drainMessage": "{{pokemonName}} 吸取了体力!", + "regainHealth": "{{pokemonName}} 回复了体力!", + "fainted": "{{pokemonNameWithAffix}} 倒下了!", + "statRose": "提高了!", + "statSharplyRose": "大幅提高了!", + "statRoseDrastically": "极大幅提高了!", + "statWontGoAnyHigher": "已经无法再提高了!", + "statFell": "降低了!", + "statHarshlyFell": "大幅降低了!", + "statSeverelyFell": "极大幅降低了!", + "statWontGoAnyLower": "已经无法再降低了!", + "ppReduced": "降低了 {{targetName}} 的\n{{moveName}} 的PP{{reduction}}点!", } as const; diff --git a/src/locales/zh_CN/berry.ts b/src/locales/zh_CN/berry.ts index 750a8bb2a2d..c13393f23a3 100644 --- a/src/locales/zh_CN/berry.ts +++ b/src/locales/zh_CN/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { @@ -45,4 +45,4 @@ export const berry: BerryTranslationEntries = { name: "苹野果", effect: "有招式的PP降到0时,恢复该招式10PP", }, -} as const; +} as const; diff --git a/src/locales/zh_CN/biome.ts b/src/locales/zh_CN/biome.ts index 3a72931e021..9026dc7fbee 100644 --- a/src/locales/zh_CN/biome.ts +++ b/src/locales/zh_CN/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "未知领域", diff --git a/src/locales/zh_CN/challenges.ts b/src/locales/zh_CN/challenges.ts index 8793f5177d7..697a97bda09 100644 --- a/src/locales/zh_CN/challenges.ts +++ b/src/locales/zh_CN/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "适用挑战条件", diff --git a/src/locales/zh_CN/command-ui-handler.ts b/src/locales/zh_CN/command-ui-handler.ts index 3ab08355aaf..57397a930df 100644 --- a/src/locales/zh_CN/command-ui-handler.ts +++ b/src/locales/zh_CN/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "战斗", diff --git a/src/locales/zh_CN/config.ts b/src/locales/zh_CN/config.ts index 3f5504f64ce..fdc54cb2be0 100644 --- a/src/locales/zh_CN/config.ts +++ b/src/locales/zh_CN/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/zh_CN/settings.js"; export const zhCnConfig = { ability: ability, @@ -74,6 +75,7 @@ export const zhCnConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/zh_CN/dialogue.ts b/src/locales/zh_CN/dialogue.ts index e8a699636b0..b9bed8fe4c4 100644 --- a/src/locales/zh_CN/dialogue.ts +++ b/src/locales/zh_CN/dialogue.ts @@ -1,4 +1,4 @@ -import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins/i18n"; +import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) export const PGMdialogue: DialogueTranslationEntries = { @@ -942,7 +942,7 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "ramos": { "encounter": { - 1: "我用那些强壮的植物\n盖出来的游乐场精彩吗?$它们的力量象征著我这个园丁兼道馆馆主的实力,\n你真的确定能够与之抗衡吗?", + 1: "我用那些强壮的植物\n盖出来的游乐场精彩吗?$它们的力量象征着我这个园丁兼道馆馆主的实力,\n你真的确定能够与之抗衡吗?", }, "victory": { 1: "你信任你的宝可梦,\n它们也信任你…不错的战斗,小豆芽。", @@ -1278,13 +1278,13 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "agatha": { "encounter": { - 1: "Pokémon are for battling! I'll show you how a real Trainer battles!" + 1: "宝可梦是为战斗而生的! \n让我来告诉你什么是真正的战斗吧!" }, "victory": { - 1: "Oh my! You're something special, child!" + 1: "呵呵!你可真是了不起!" }, "defeat": { - 1: "Bahaha. That's how a proper battle's done!" + 1: "额哈哈哈,真正的战斗就是该这样。" } }, "flint": { @@ -2009,28 +2009,28 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "alder": { "encounter": { - 1: "Prepare yourself for a match against the strongest Trainer in Unova!" + 1: "准备好和合众最强的训练家交手吧!" }, "victory": { - 1: "Well done! You certainly are an unmatched talent." + 1: "精彩!简直就是天下无双!" }, "defeat": { - 1: `A fresh wind blows through my heart... - $What an extraordinary effort!` + 1: `战斗结束后,我的心像是吹过了温和的风…… + $真是厉害!` } }, "kieran": { "encounter": { - 1: `Through hard work, I become stronger and stronger! - $I don't lose.` + 1: `我的努力让我越来越强! + $所以我不会输。` }, "victory": { - 1: `I don't believe it... - $What a fun and heart-pounding battle!` + 1: `不可能…… + $真是一场有趣又激动人心的战斗啊!` }, "defeat": { - 1: `Wowzers, what a battle! - $Time for you to train even harder.` + 1: `哇塞,好一场战斗! + $你得多练练了。` } }, "rival": { @@ -2062,7 +2062,7 @@ export const PGMdialogue: DialogueTranslationEntries = { 1: "@c{smile_wave}哦,真巧,在这里遇见你。\n看来你还没输过嘛。@c{angry_mopen}哈……好家伙!$@c{angry_mopen}我知道你在想什么,\n不,我才不会跟踪你什么呢。 @c{smile_eclosed}我只是碰巧在附近。$@c{smile_ehalf}我为你感到高兴,但我只想让你知道\n有时输了是可以接受的。$@c{smile}我们从错误中学到的东西\n往往比我们一直成功时学到的还要多。$@c{angry_mopen}无论如何,我为了我们的复赛已经努力训练了\n所以你最好全力以赴!", }, "victory": { - 1: "@c{neutral}我……没打算会输来着……$@c{smile}嗷……好吧。看来我要再更加努力训练了!$@c{smile_wave}我还给你带了个这个$@c{smile_wave_wink}不用谢我哦~.$@c{angry_mopen}不过,这是最后一个啦!\n 你可别想再从我这赚小便宜了~$@c{smile_wave}要保重哦!", + 1: "@c{neutral}我……没打算会输来着……$@c{smile}嗷……好吧。看来我要再更加努力训练了!$@c{smile_wave}我还给你带了个这个$@c{smile_wave_wink}不用谢我哦~.$@c{angry_mopen}不过,这是最后一个啦!\n你可别想再从我这赚小便宜了~$@c{smile_wave}要保重哦!", }, "defeat": { 1: "输了有时候也不要紧的…", @@ -2070,7 +2070,7 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "rival_3": { "encounter": { - 1: "@c{smile}}嘿,看看这是谁!好久不见啊。$@c{neutral}你……还是没输过?哈…$@c{neutral_eclosed}这有点……不太对劲。$没有你一起,回家的感觉有很不一样。$@c{serious}虽然我知道这挺别扭的,但我就直说了。$@c{neutral_eclosed}我觉得你有点儿难以理喻。$@c{serious}没有人能够战无不胜。$失败乃成功之母。$@c{neutral_eclosed}你已经赢得了够好的成绩,\n但前面道阻且长,只会愈发艰难。 @c{neutral}你做好准备了没?$@c{serious_mopen_fists}如果做好了,证明给我看吧。", + 1: "@c{smile}嘿,看看这是谁!好久不见啊。$@c{neutral}你……还是没输过?哈…$@c{neutral_eclosed}这有点……不太对劲。$没有你一起,回家的感觉有很不一样。$@c{serious}虽然我知道这挺别扭的,但我就直说了。$@c{neutral_eclosed}我觉得你有点儿难以理喻。$@c{serious}没有人能够战无不胜。$失败乃成功之母。$@c{neutral_eclosed}你已经赢得了够好的成绩,\n但前面道阻且长,只会愈发艰难。 @c{neutral}你做好准备了没?$@c{serious_mopen_fists}如果做好了,证明给我看吧。", }, "victory": { 1: "@c{angry_mhalf}这太离谱了……我几乎从没停下训练……$我们之间的差距怎么还是这么大?", @@ -2078,7 +2078,7 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "rival_3_female": { "encounter": { - 1: "@c{smile_wave}好久不见!还没输过,对吧。$@c{angry}我觉得你点烦了。@c{smile_wave_wink}开玩笑啦!$@c{smile_ehalf}但说真的,你现在不想家吗?\n 不想…我吗?$我……我的意思是,我们真的很想你。$@c{smile_eclosed}我支持你的一切,包括你的梦想。\n但现实就是你早晚会经历失败。$@c{smile}当你失败的时候,我想像往常一样陪在你身边。$@c{angry_mopen}}现在,给你看看我变得多强了吧!", + 1: "@c{smile_wave}好久不见!还没输过,对吧。$@c{angry}我觉得你点烦了。@c{smile_wave_wink}开玩笑啦!$@c{smile_ehalf}但说真的,你现在不想家吗?\n不想…我吗?$我……我的意思是,我们真的很想你。$@c{smile_eclosed}我支持你的一切,包括你的梦想。\n但现实就是你早晚会经历失败。$@c{smile}当你失败的时候,我想像往常一样陪在你身边。$@c{angry_mopen}现在,给你看看我变得多强了吧!", }, "victory": { 1: "@c{shock}都这样了……还是不够吗?$这样下去,你就永远不会回来了……", @@ -2136,7 +2136,7 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "rival_6_female": { "encounter": { - 1: "@c{smile_ehalf}又只有我们两个人了。$@c{smile_eclosed}你知道吗,我在心里想啊想,\n想了好久……$@c{smile_ehalf}这一切背后是有什么原因吗,\n为什么一切现在看起来都这么奇怪……$@c{smile}你有你的梦想,而我内心有这个抱负……$我不禁感觉这一切背后有一个更庞大的力量,$掌控者我们所做的一切,你和我之间。$@c{smile_eclosed}}我想我注定要推动你……到你的极限。$@c{smile_ehalf}我不清楚我是否一直做得很好,\n但到现在为止,我已经尽力了。$这个奇怪而可怕的地方……\n一切看起来都那么清晰……$这是世界早已记录的一切。$@c{smile_eclosed}我好像记不清我们一起度过的日子了。$@c{smile_ehalf}那些回忆到底是真的吗?\n怎么感觉这么久远……$@c{angry_mopen}你得继续前进,不然的话,这一切将永无止境。\n你是唯一能做到这件事的。$@c{smile_ehalf}}我……不知道这一切意味着什么……\n但我明白$@c{neutral}如果你现在不能就此击败我,\n你将毫无机会可言。", + 1: "@c{smile_ehalf}又只有我们两个人了。$@c{smile_eclosed}你知道吗,我在心里想啊想,\n想了好久……$@c{smile_ehalf}这一切背后是有什么原因吗,\n为什么一切现在看起来都这么奇怪……$@c{smile}你有你的梦想,而我内心有这个抱负……$我不禁感觉这一切背后有一个更庞大的力量,$掌控者我们所做的一切,你和我之间。$@c{smile_eclosed}我想我注定要推动你……到你的极限。$@c{smile_ehalf}我不清楚我是否一直做得很好,\n但到现在为止,我已经尽力了。$这个奇怪而可怕的地方……\n一切看起来都那么清晰……$这是世界早已记录的一切。$@c{smile_eclosed}我好像记不清我们一起度过的日子了。$@c{smile_ehalf}那些回忆到底是真的吗?\n怎么感觉这么久远……$@c{angry_mopen}你得继续前进,不然的话,这一切将永无止境。\n你是唯一能做到这件事的。$@c{smile_ehalf}我……不知道这一切意味着什么……\n但我明白$@c{neutral}如果你现在不能就此击败我,\n你将毫无机会可言。", }, "victory": { 1: "@c{smile_ehalf}我……\n我想我完成了我的使命……$@c{smile_eclosed}答应我……在你拯救世界之后\n……要……平安到家。$@c{smile_ehalf}……谢谢你。", @@ -2155,7 +2155,7 @@ export const PGMbattleSpecDialogue: SimpleTranslationEntries = { $你被吸引到这里,因为你以前就来过这里。\n无数次。 $尽管,或许可以数一数。\n准确地说,这实际上是你的第5,643,853次循环。 $每一次循环,你的思想都会恢复到之前的状态。\n即便如此,不知何故,你之前自我的残留仍然存在。 - $直到现在,你仍未成功,但我感觉这次你身上有一种异样的气息。\n + $直到现在,你仍未成功,\n但我感觉这次你身上有一种异样的气息。 $你是这里唯一的人,尽管感觉上还有……另一个人。 $你最终会成为对我来的一个硬茬吗?\n我渴望了数千年的挑战? $我们,开始。`, diff --git a/src/locales/zh_CN/egg.ts b/src/locales/zh_CN/egg.ts index 99916ab0778..0ea464ca5a9 100644 --- a/src/locales/zh_CN/egg.ts +++ b/src/locales/zh_CN/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "蛋", diff --git a/src/locales/zh_CN/fight-ui-handler.ts b/src/locales/zh_CN/fight-ui-handler.ts index 7ccab7561da..07865250d9f 100644 --- a/src/locales/zh_CN/fight-ui-handler.ts +++ b/src/locales/zh_CN/fight-ui-handler.ts @@ -1,9 +1,9 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", "power": "威力", "accuracy": "命中", - "abilityFlyInText": " {{pokemonName}}'s {{passive}}{{abilityName}}", - "passive": "Passive ", // The space at the end is important + "abilityFlyInText": " {{pokemonName}} 的 {{passive}}{{abilityName}}", + "passive": "被动 ", // The space at the end is important } as const; diff --git a/src/locales/zh_CN/game-mode.ts b/src/locales/zh_CN/game-mode.ts index be342b4c390..ed96ac4c78e 100644 --- a/src/locales/zh_CN/game-mode.ts +++ b/src/locales/zh_CN/game-mode.ts @@ -1,10 +1,10 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { - "classic": "Classic", - "endless": "Endless", - "endlessSpliced": "Endless (Spliced)", - "dailyRun": "Daily Run", - "unknown": "Unknown", - "challenge": "Challenge", + "classic": "经典模式", + "endless": "无尽模式", + "endlessSpliced": "融合无尽模式", + "dailyRun": "每日挑战", + "unknown": "未知", + "challenge": "挑战模式", } as const; diff --git a/src/locales/zh_CN/game-stats-ui-handler.ts b/src/locales/zh_CN/game-stats-ui-handler.ts index f44e1d8b9e9..9fb3b9f5af8 100644 --- a/src/locales/zh_CN/game-stats-ui-handler.ts +++ b/src/locales/zh_CN/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "统计", diff --git a/src/locales/zh_CN/growth.ts b/src/locales/zh_CN/growth.ts index 33a1dec8bb8..9362810c4f8 100644 --- a/src/locales/zh_CN/growth.ts +++ b/src/locales/zh_CN/growth.ts @@ -1,10 +1,10 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { - "Erratic": "最快", - "Fast": "较快", - "Medium_Fast": "快", - "Medium_Slow": "慢", - "Slow": "较慢", - "Fluctuating": "最慢" -} as const; + "Erratic": "非常快", + "Fast": "快", + "Medium_Fast": "较快", + "Medium_Slow": "较慢", + "Slow": "慢", + "Fluctuating": "非常慢" +} as const; diff --git a/src/locales/zh_CN/menu-ui-handler.ts b/src/locales/zh_CN/menu-ui-handler.ts index e3d0d158e33..6107c1c2800 100644 --- a/src/locales/zh_CN/menu-ui-handler.ts +++ b/src/locales/zh_CN/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "游戏设置", diff --git a/src/locales/zh_CN/menu.ts b/src/locales/zh_CN/menu.ts index 39d8e5e3a04..97af66c8d3a 100644 --- a/src/locales/zh_CN/menu.ts +++ b/src/locales/zh_CN/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,8 +34,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "会话加载成功。", "failedToLoadSession": "无法加载您的会话数据。它可能已损坏。", "boyOrGirl": "你是男孩还是女孩?", - "boy": "男孩", - "girl": "女孩", "evolving": "咦?\n{{pokemonName}} 开始进化了!", "stoppedEvolving": "{{pokemonName}} 停止了进化。", "pauseEvolutionsQuestion": "你确定要停止 {{pokemonName}} 的进化吗?\n你可以在队伍界面中重新进化。", @@ -44,11 +42,15 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "每日排名", "weeklyRankings": "每周排名", "noRankings": "无排名", + "positionIcon": "#", + "usernameScoreboard": "用户名", + "score": "分数", + "wave": "层数", "loading": "加载中...", - "loadingAsset": "Loading asset: {{assetName}}", + "loadingAsset": "加载资源: {{assetName}}", "playersOnline": "在线玩家", "yes": "是", "no": "否", - "disclaimer": "DISCLAIMER", - "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed." + "disclaimer": "免责声明", + "disclaimerDescription": "这个游戏尚未完成; 可能存在游戏性问题(包括潜在的丢档风险)、\n 不经通知的调整、 未来可能会更新或完成更多内容", } as const; diff --git a/src/locales/zh_CN/modifier-type.ts b/src/locales/zh_CN/modifier-type.ts index c94c8e4b04f..52971fe08f3 100644 --- a/src/locales/zh_CN/modifier-type.ts +++ b/src/locales/zh_CN/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { @@ -93,7 +93,7 @@ export const modifierType: ModifierTypeTranslationEntries = { description: "招式命中率增加{{accuracyAmount}} (最大100)。", }, "PokemonMultiHitModifierType": { - description: "攻击造成一次额外伤害,每次堆叠额外伤害\n分别衰减60/75/82.5%。", + description: "攻击造成一次额外伤害,\n每堆叠一件会让攻击伤害\n衰减60/75/82.5%。", }, "TmModifierType": { name: "招式学习器 {{moveId}} - {{moveName}}", @@ -126,7 +126,7 @@ export const modifierType: ModifierTypeTranslationEntries = { description: "攻击时{{chancePercent}}%概率造成{{statusEffect}}。", }, "EnemyEndureChanceModifierType": { - description: "增加{{chancePercent}}%遭受攻击的概率。", + description: "敌方增加{{chancePercent}}%的概率在本回合不会倒下。", }, "RARE_CANDY": { name: "神奇糖果" }, @@ -213,8 +213,8 @@ export const modifierType: ModifierTypeTranslationEntries = { "LEFTOVERS": { name: "吃剩的东西", description: "携带该道具的宝可梦在每个回合结束时恢复\n最大HP的1/16。" }, "SHELL_BELL": { name: "贝壳之铃", description: "携带该道具的宝可梦在攻击对方成功造成伤\n害时,携带者的HP会恢复其所造成伤害\n的1/8。" }, - "TOXIC_ORB": { name: "Toxic Orb", description: "触碰后会放出毒的神奇宝珠。携带后,在战斗时会变成剧毒状态。" }, - "FLAME_ORB": { name: "Flame Orb", description: "触碰后会放出热量的神奇宝珠。携带后,在战斗时会变成灼伤状态。" }, + "TOXIC_ORB": { name: "剧毒宝珠", description: "触碰后会放出毒的神奇宝珠。携带后,在战斗时会变成剧毒状态。" }, + "FLAME_ORB": { name: "火焰宝珠", description: "触碰后会放出热量的神奇宝珠。携带后,在战斗时会变成灼伤状态。" }, "BATON": { name: "接力棒", description: "允许在切换宝可梦时保留能力变化, 对陷阱\n同样生效。" }, @@ -229,8 +229,8 @@ export const modifierType: ModifierTypeTranslationEntries = { "GOLDEN_POKEBALL": { name: "黄金精灵球", description: "在每场战斗结束后增加一个额外物品选项。" }, - "ENEMY_DAMAGE_BOOSTER": { name: "伤害硬币", description: "增加5%造成伤害。" }, - "ENEMY_DAMAGE_REDUCTION": { name: "防御硬币", description: "减少2.5%承受伤害。" }, + "ENEMY_DAMAGE_BOOSTER": { name: "伤害硬币", description: "造成5%额外伤害(乘算)。" }, + "ENEMY_DAMAGE_REDUCTION": { name: "防御硬币", description: "受到2.5%更少伤害(乘算)。" }, "ENEMY_HEAL": { name: "回复硬币", description: "每回合回复2%最大HP。" }, "ENEMY_ATTACK_POISON_CHANCE": { name: "剧毒硬币" }, "ENEMY_ATTACK_PARALYZE_CHANCE": { name: "麻痹硬币" }, @@ -250,14 +250,14 @@ export const modifierType: ModifierTypeTranslationEntries = { }, TempBattleStatBoosterStatName: { - "ATK": "Attack", - "DEF": "Defense", - "SPATK": "Sp. Atk", - "SPDEF": "Sp. Def", - "SPD": "Speed", - "ACC": "Accuracy", - "CRIT": "Critical Hit Ratio", - "EVA": "Evasiveness", + "ATK": "攻击", + "DEF": "防御", + "SPATK": "特攻", + "SPDEF": "特防", + "SPD": "速度", + "ACC": "命中", + "CRIT": "会心", + "EVA": "闪避", "DEFAULT": "???", }, @@ -290,7 +290,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "carbos": "速度增强剂", }, EvolutionItem: { - "NONE": "None", + "NONE": "无", "LINKING_CORD": "联系绳", "SUN_STONE": "日之石", @@ -323,7 +323,7 @@ export const modifierType: ModifierTypeTranslationEntries = { "SYRUPY_APPLE": "蜜汁苹果", }, FormChangeItem: { - "NONE": "None", + "NONE": "无", "ABOMASITE": "暴雪王进化石", "ABSOLITE": "阿勃梭鲁进化石", diff --git a/src/locales/zh_CN/move.ts b/src/locales/zh_CN/move.ts index dfbd66bcf4f..e51addd0206 100644 --- a/src/locales/zh_CN/move.ts +++ b/src/locales/zh_CN/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { "pound": { diff --git a/src/locales/zh_CN/nature.ts b/src/locales/zh_CN/nature.ts index 80fd8d89869..d4447e8b03d 100644 --- a/src/locales/zh_CN/nature.ts +++ b/src/locales/zh_CN/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "勤奋", diff --git a/src/locales/zh_CN/party-ui-handler.ts b/src/locales/zh_CN/party-ui-handler.ts index 6f4f4f4c88a..52529bf8fa9 100644 --- a/src/locales/zh_CN/party-ui-handler.ts +++ b/src/locales/zh_CN/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "SEND_OUT": "上场", diff --git a/src/locales/zh_CN/pokeball.ts b/src/locales/zh_CN/pokeball.ts index 6bf20f7e276..b8df88983bb 100644 --- a/src/locales/zh_CN/pokeball.ts +++ b/src/locales/zh_CN/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "精灵球", diff --git a/src/locales/zh_CN/pokemon-info-container.ts b/src/locales/zh_CN/pokemon-info-container.ts index fae75e773b9..f7072276e65 100644 --- a/src/locales/zh_CN/pokemon-info-container.ts +++ b/src/locales/zh_CN/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "招式", diff --git a/src/locales/zh_CN/pokemon-info.ts b/src/locales/zh_CN/pokemon-info.ts index 7c72acb1b2a..f7aaf3a33cb 100644 --- a/src/locales/zh_CN/pokemon-info.ts +++ b/src/locales/zh_CN/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { @@ -14,8 +14,8 @@ export const pokemonInfo: PokemonInfoTranslationEntries = { "SPDEFshortened": "特防", "SPD": "速度", "SPDshortened": "速度", - "ACC": "Accuracy", - "EVA": "Evasiveness" + "ACC": "命中率", + "EVA": "回避率" }, Type: { diff --git a/src/locales/zh_CN/pokemon.ts b/src/locales/zh_CN/pokemon.ts index 6d6e372046e..5ff670637f4 100644 --- a/src/locales/zh_CN/pokemon.ts +++ b/src/locales/zh_CN/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "妙蛙种子", diff --git a/src/locales/zh_CN/save-slot-select-ui-handler.ts b/src/locales/zh_CN/save-slot-select-ui-handler.ts index 0d657235e49..001ecbe2d00 100644 --- a/src/locales/zh_CN/save-slot-select-ui-handler.ts +++ b/src/locales/zh_CN/save-slot-select-ui-handler.ts @@ -1,9 +1,9 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { - "overwriteData": "Overwrite the data in the selected slot?", + "overwriteData": "要覆盖该槽位的存档吗?", "loading": "正在加载中...", - "wave": "Wave", + "wave": "层数", "lv": "Lv", "empty": "空", } as const; diff --git a/src/locales/zh_CN/settings.ts b/src/locales/zh_CN/settings.ts new file mode 100644 index 00000000000..04df61d7dbe --- /dev/null +++ b/src/locales/zh_CN/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "男孩", + "girl": "女孩", + "general": "常规", + "display": "显示", + "audio": "音频", + "gamepad": "手柄", + "keyboard": "键盘", + "gameSpeed": "游戏速度", + "hpBarSpeed": "血条速度", + "expGainsSpeed": "经验值获取动画速度", + "expPartyDisplay": "显示队伍经验", + "skipSeenDialogues": "跳过已读对话", + "battleStyle": "对战模式", + "enableRetries": "允许重试", + "tutorials": "教程", + "touchControls": "触摸操作", + "vibrations": "手柄震动", + "normal": "普通", + "fast": "快", + "faster": "更快", + "skip": "跳过", + "levelUpNotifications": "升级提示", + "on": "启用", + "off": "禁用", + "switch": "切换", + "set": "固定", + "auto": "自动", + "disabled": "禁用", + "language": "语言", + "change": "选择", + "uiTheme": "界面风格", + "default": "默认", + "legacy": "经典", + "windowType": "窗口类型", + "moneyFormat": "金钱格式", + "damageNumbers": "伤害数字", + "simple": "简单", + "fancy": "华丽", + "abbreviated": "缩略", + "moveAnimations": "招式动画", + "showStatsOnLevelUp": "升级时显示能力值", + "candyUpgradeNotification": "糖果升级提示", + "passivesOnly": "仅被动", + "candyUpgradeDisplay": "糖果升级显示", + "icon": "图标", + "animation": "动画", + "moveInfo": "招式信息", + "showMovesetFlyout": "显示招式池弹窗", + "showArenaFlyout": "显示战场弹窗", + "showTimeOfDayWidget": "显示时间指示器", + "timeOfDayAnimation": "时间指示器动画", + "bounce": "彈一下", + "timeOfDay_back": "不彈", + "spriteSet": "宝可梦动画", + "consistent": "默认", + "mixedAnimated": "全部动画", + "fusionPaletteSwaps": "融合色调切换", + "playerGender": "玩家性别", + "typeHints": "属性提示", + "masterVolume": "主音量", + "bgmVolume": "音乐", + "seVolume": "音效", + "musicPreference": "音乐偏好", + "mixed": "全曲混合", + "gamepadPleasePlug": "请链接手柄或按任意键", + "delete": "删除", + "keyboardPleasePress": "请点击键盘上的对应按键", + "reset": "重置", + "requireReload": "需要重新加载", + "action": "操作", + "back": "返回", + "pressToBind": "按下以绑定", + "pressButton": "请按键……", + "buttonUp": "上", + "buttonDown": "下", + "buttonLeft": "左", + "buttonRight": "右", + "buttonAction": "确认", + "buttonMenu": "菜单", + "buttonSubmit": "提交", + "buttonCancel": "取消", + "buttonStats": "状态", + "buttonCycleForm": "切换形态", + "buttonCycleShiny": "切换闪光", + "buttonCycleGender": "切换性别", + "buttonCycleAbility": "切换特性", + "buttonCycleNature": "切换性格", + "buttonCycleVariant": "切换变种", + "buttonSpeedUp": "加速", + "buttonSlowDown": "减速", + "alt": " (备用)", + "mute": "静音", + "controller": "控制器", + "gamepadSupport": "手柄支持" +} as const; diff --git a/src/locales/zh_CN/splash-messages.ts b/src/locales/zh_CN/splash-messages.ts index 1d5cf09fc16..dfa5cc4529d 100644 --- a/src/locales/zh_CN/splash-messages.ts +++ b/src/locales/zh_CN/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "Battles Won!", diff --git a/src/locales/zh_CN/starter-select-ui-handler.ts b/src/locales/zh_CN/starter-select-ui-handler.ts index 803e64e0439..669b8a5bb80 100644 --- a/src/locales/zh_CN/starter-select-ui-handler.ts +++ b/src/locales/zh_CN/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "addToParty": "加入队伍", "toggleIVs": "切换个体值", "manageMoves": "管理招式", + "manageNature": "管理性格", "useCandies": "使用糖果", + "selectNature": "选择性格", "selectMoveSwapOut": "选择要替换的招式。", "selectMoveSwapWith": "选择要替换成的招式", "unlockPassive": "解锁被动", diff --git a/src/locales/zh_CN/trainers.ts b/src/locales/zh_CN/trainers.ts index 28b0760cc9b..9d7f647b891 100644 --- a/src/locales/zh_CN/trainers.ts +++ b/src/locales/zh_CN/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { @@ -48,7 +48,7 @@ export const trainerClasses: SimpleTranslationEntries = { "depot_agent": "铁路员工", "doctor": "医生", "doctor_female": "医生", - "firebreather": "Firebreather", + "firebreather": "吹火人", "fisherman": "垂钓者", "fisherman_female": "垂钓者", "gentleman": "绅士", @@ -87,13 +87,13 @@ export const trainerClasses: SimpleTranslationEntries = { "pokémon_rangers": "宝可梦巡护员组合", "ranger": "巡护员", "restaurant_staff": "服务生组合", - "rich": "Rich", - "rich_female": "Rich", + "rich": "富豪", + "rich_female": "富豪太太", "rich_boy": "富家少爷", "rich_couple": "富豪夫妇", - "rich_kid": "Rich Kid", - "rich_kid_female": "Rich Kid", - "rich_kids": "富二代组合", + "rich_kid": "富家小孩", + "rich_kid_female": "富家小孩", + "rich_kids": "富家小孩组合", "roughneck": "光头男", "sailor": "水手", "scientist": "研究员", diff --git a/src/locales/zh_CN/tutorial.ts b/src/locales/zh_CN/tutorial.ts index 8b0e5aad8fd..e9c428aac9f 100644 --- a/src/locales/zh_CN/tutorial.ts +++ b/src/locales/zh_CN/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `欢迎来到PokéRogue!这是一款以战斗为核心的\n融合了roguelite元素的宝可梦同人游戏。 diff --git a/src/locales/zh_CN/voucher.ts b/src/locales/zh_CN/voucher.ts index f7ef39b1df3..613c96c6da8 100644 --- a/src/locales/zh_CN/voucher.ts +++ b/src/locales/zh_CN/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "兑换券", @@ -8,4 +8,4 @@ export const voucher: SimpleTranslationEntries = { "eggVoucherGold": "黄金扭蛋券", "locked": "锁定", "defeatTrainer": "你打败了{{trainerName}}" -} as const; +} as const; diff --git a/src/locales/zh_CN/weather.ts b/src/locales/zh_CN/weather.ts index 874b17f8fe8..ad1ecc65007 100644 --- a/src/locales/zh_CN/weather.ts +++ b/src/locales/zh_CN/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/locales/zh_TW/ability-trigger.ts b/src/locales/zh_TW/ability-trigger.ts index 1281a8720c1..8dcbd0e8408 100644 --- a/src/locales/zh_TW/ability-trigger.ts +++ b/src/locales/zh_TW/ability-trigger.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const abilityTriggers: SimpleTranslationEntries = { "blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!", diff --git a/src/locales/zh_TW/ability.ts b/src/locales/zh_TW/ability.ts index a99d0acd10c..9fa520a81ff 100644 --- a/src/locales/zh_TW/ability.ts +++ b/src/locales/zh_TW/ability.ts @@ -1,4 +1,4 @@ -import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; +import { AbilityTranslationEntries } from "#app/interfaces/locales.js"; export const ability: AbilityTranslationEntries = { stench: { diff --git a/src/locales/zh_TW/achv.ts b/src/locales/zh_TW/achv.ts index bf1bfc295e8..4f59ecb2135 100644 --- a/src/locales/zh_TW/achv.ts +++ b/src/locales/zh_TW/achv.ts @@ -1,4 +1,4 @@ -import { AchievementTranslationEntries } from "#app/plugins/i18n.js"; +import { AchievementTranslationEntries } from "#app/interfaces/locales.js"; // Achievement translations for the when the player character is male export const PGMachv: AchievementTranslationEntries = { diff --git a/src/locales/zh_TW/battle-message-ui-handler.ts b/src/locales/zh_TW/battle-message-ui-handler.ts index 3f8892749fe..3cd63de7961 100644 --- a/src/locales/zh_TW/battle-message-ui-handler.ts +++ b/src/locales/zh_TW/battle-message-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battleMessageUiHandler: SimpleTranslationEntries = { "ivBest": "最棒", diff --git a/src/locales/zh_TW/battle.ts b/src/locales/zh_TW/battle.ts index 224a9f2bf0f..f8179c50887 100644 --- a/src/locales/zh_TW/battle.ts +++ b/src/locales/zh_TW/battle.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const battle: SimpleTranslationEntries = { "bossAppeared": "{{bossName}} 出現了.", @@ -67,4 +67,5 @@ export const battle: SimpleTranslationEntries = { "statHarshlyFell": "harshly fell", "statSeverelyFell": "severely fell", "statWontGoAnyLower": "won't go any lower", + "ppReduced": "It reduced the PP of {{targetName}}'s\n{{moveName}} by {{reduction}}!", } as const; diff --git a/src/locales/zh_TW/berry.ts b/src/locales/zh_TW/berry.ts index 931efb2c22f..a084ef91aa5 100644 --- a/src/locales/zh_TW/berry.ts +++ b/src/locales/zh_TW/berry.ts @@ -1,4 +1,4 @@ -import { BerryTranslationEntries } from "#app/plugins/i18n"; +import { BerryTranslationEntries } from "#app/interfaces/locales"; export const berry: BerryTranslationEntries = { "SITRUS": { diff --git a/src/locales/zh_TW/biome.ts b/src/locales/zh_TW/biome.ts index 5631b91b836..d3f34c021d4 100644 --- a/src/locales/zh_TW/biome.ts +++ b/src/locales/zh_TW/biome.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const biome: SimpleTranslationEntries = { "unknownLocation": "Somewhere you can\'t remember", diff --git a/src/locales/zh_TW/challenges.ts b/src/locales/zh_TW/challenges.ts index c98b68137ad..9da058001b1 100644 --- a/src/locales/zh_TW/challenges.ts +++ b/src/locales/zh_TW/challenges.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const challenges: SimpleTranslationEntries = { "title": "適用挑戰條件", diff --git a/src/locales/zh_TW/command-ui-handler.ts b/src/locales/zh_TW/command-ui-handler.ts index 6431d903447..9fad34bb64f 100644 --- a/src/locales/zh_TW/command-ui-handler.ts +++ b/src/locales/zh_TW/command-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const commandUiHandler: SimpleTranslationEntries = { "fight": "戰鬥", diff --git a/src/locales/zh_TW/config.ts b/src/locales/zh_TW/config.ts index 49e82f3b436..5d6a2dd978d 100644 --- a/src/locales/zh_TW/config.ts +++ b/src/locales/zh_TW/config.ts @@ -39,6 +39,7 @@ import { tutorial } from "./tutorial"; import { voucher } from "./voucher"; import { weather } from "./weather"; import { partyUiHandler } from "./party-ui-handler"; +import { settings } from "#app/locales/zh_TW/settings.js"; export const zhTwConfig = { ability: ability, @@ -74,6 +75,7 @@ export const zhTwConfig = { pokemonInfo: pokemonInfo, pokemonInfoContainer: pokemonInfoContainer, saveSlotSelectUiHandler: saveSlotSelectUiHandler, + settings: settings, splashMessages: splashMessages, starterSelectUiHandler: starterSelectUiHandler, titles: titles, diff --git a/src/locales/zh_TW/dialogue.ts b/src/locales/zh_TW/dialogue.ts index e563479a12b..119f9e8bb8f 100644 --- a/src/locales/zh_TW/dialogue.ts +++ b/src/locales/zh_TW/dialogue.ts @@ -1,4 +1,4 @@ -import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/plugins/i18n"; +import {DialogueTranslationEntries, SimpleTranslationEntries} from "#app/interfaces/locales"; // Dialogue of the NPCs in the game when the player character is male (or unset) export const PGMdialogue: DialogueTranslationEntries = { @@ -2009,28 +2009,28 @@ export const PGMdialogue: DialogueTranslationEntries = { }, "alder": { "encounter": { - 1: "Prepare yourself for a match against the strongest Trainer in Unova!" + 1: "準備好和合眾最強的訓練家交手吧!" }, "victory": { - 1: "Well done! You certainly are an unmatched talent." + 1: "精彩!簡直就是天下無雙!" }, "defeat": { - 1: `A fresh wind blows through my heart... - $What an extraordinary effort!` + 1: `戰鬥結束後,我的心像是吹過了溫和的風… + $真是厲害!` } }, "kieran": { "encounter": { - 1: `Through hard work, I become stronger and stronger! - $I don't lose.` + 1: `我的努力讓我越來越強! + $所以我不會輸。` }, "victory": { - 1: `I don't believe it... - $What a fun and heart-pounding battle!` + 1: `不可能… + $真是一場有趣又激動人心的戰鬥啊!` }, "defeat": { - 1: `Wowzers, what a battle! - $Time for you to train even harder.` + 1: `哇塞,好一場戰鬥! + $你得多練練了。` } }, "rival": { diff --git a/src/locales/zh_TW/egg.ts b/src/locales/zh_TW/egg.ts index d25599036b0..9668385f71e 100644 --- a/src/locales/zh_TW/egg.ts +++ b/src/locales/zh_TW/egg.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const egg: SimpleTranslationEntries = { "egg": "蛋", diff --git a/src/locales/zh_TW/fight-ui-handler.ts b/src/locales/zh_TW/fight-ui-handler.ts index 64df373ea7a..6885d0fcc2a 100644 --- a/src/locales/zh_TW/fight-ui-handler.ts +++ b/src/locales/zh_TW/fight-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", diff --git a/src/locales/zh_TW/game-mode.ts b/src/locales/zh_TW/game-mode.ts index be342b4c390..903f1a63072 100644 --- a/src/locales/zh_TW/game-mode.ts +++ b/src/locales/zh_TW/game-mode.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameMode: SimpleTranslationEntries = { "classic": "Classic", diff --git a/src/locales/zh_TW/game-stats-ui-handler.ts b/src/locales/zh_TW/game-stats-ui-handler.ts index cb3228c1a4a..a29eaf5d1b6 100644 --- a/src/locales/zh_TW/game-stats-ui-handler.ts +++ b/src/locales/zh_TW/game-stats-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const gameStatsUiHandler: SimpleTranslationEntries = { "stats": "Stats", diff --git a/src/locales/zh_TW/growth.ts b/src/locales/zh_TW/growth.ts index 941ddb39e66..a67f108052a 100644 --- a/src/locales/zh_TW/growth.ts +++ b/src/locales/zh_TW/growth.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const growth: SimpleTranslationEntries = { "Erratic": "最快", diff --git a/src/locales/zh_TW/menu-ui-handler.ts b/src/locales/zh_TW/menu-ui-handler.ts index c38b447effd..6108b732d95 100644 --- a/src/locales/zh_TW/menu-ui-handler.ts +++ b/src/locales/zh_TW/menu-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const menuUiHandler: SimpleTranslationEntries = { "GAME_SETTINGS": "遊戲設置", diff --git a/src/locales/zh_TW/menu.ts b/src/locales/zh_TW/menu.ts index d16052f2ac7..443b569d908 100644 --- a/src/locales/zh_TW/menu.ts +++ b/src/locales/zh_TW/menu.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -34,8 +34,6 @@ export const menu: SimpleTranslationEntries = { "sessionSuccess": "工作階段加載成功.", "failedToLoadSession": "無法加載您的工作階段數據。它可能已損壞。", "boyOrGirl": "你是男孩還是女孩?", - "boy": "男孩", - "girl": "女孩", "evolving": "甚麼?\n{{pokemonName}} 要進化了!", "stoppedEvolving": "{{pokemonName}} 停止了進化。", "pauseEvolutionsQuestion": "你確定要停止 {{pokemonName}} 的進化嗎?\n你可以在隊伍畫面中重新啟用進化。", @@ -44,11 +42,15 @@ export const menu: SimpleTranslationEntries = { "dailyRankings": "每日排名", "weeklyRankings": "每週排名", "noRankings": "無排名", + "positionIcon": "#", + "usernameScoreboard": "Username", + "score": "Score", + "wave": "Wave", "loading": "加載中…", "loadingAsset": "Loading asset: {{assetName}}", "playersOnline": "在線玩家", "yes":"是", "no":"否", "disclaimer": "DISCLAIMER", - "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed." + "disclaimerDescription": "This game is an unfinished product; it might have playability issues (including the potential loss of save data),\n change without notice, and may or may not be updated further or completed.", } as const; diff --git a/src/locales/zh_TW/modifier-type.ts b/src/locales/zh_TW/modifier-type.ts index f44c6efef84..769c01e072f 100644 --- a/src/locales/zh_TW/modifier-type.ts +++ b/src/locales/zh_TW/modifier-type.ts @@ -1,4 +1,4 @@ -import { ModifierTypeTranslationEntries } from "#app/plugins/i18n"; +import { ModifierTypeTranslationEntries } from "#app/interfaces/locales"; export const modifierType: ModifierTypeTranslationEntries = { ModifierType: { diff --git a/src/locales/zh_TW/move.ts b/src/locales/zh_TW/move.ts index 87e19a0b531..0a6321850db 100644 --- a/src/locales/zh_TW/move.ts +++ b/src/locales/zh_TW/move.ts @@ -1,4 +1,4 @@ -import { MoveTranslationEntries } from "#app/plugins/i18n"; +import { MoveTranslationEntries } from "#app/interfaces/locales"; export const move: MoveTranslationEntries = { pound: { name: "拍擊", effect: "使用長長的尾巴或手等拍打\n對手進行攻擊" }, diff --git a/src/locales/zh_TW/nature.ts b/src/locales/zh_TW/nature.ts index 10ca9c71939..f72d271c139 100644 --- a/src/locales/zh_TW/nature.ts +++ b/src/locales/zh_TW/nature.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const nature: SimpleTranslationEntries = { "Hardy": "勤奮", diff --git a/src/locales/zh_TW/party-ui-handler.ts b/src/locales/zh_TW/party-ui-handler.ts index 9d3c7baa9ae..894ea14bb12 100644 --- a/src/locales/zh_TW/party-ui-handler.ts +++ b/src/locales/zh_TW/party-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const partyUiHandler: SimpleTranslationEntries = { "SEND_OUT": "Send Out", diff --git a/src/locales/zh_TW/pokeball.ts b/src/locales/zh_TW/pokeball.ts index ce3d7a7a860..8919f3591e1 100644 --- a/src/locales/zh_TW/pokeball.ts +++ b/src/locales/zh_TW/pokeball.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokeball: SimpleTranslationEntries = { "pokeBall": "精靈球", diff --git a/src/locales/zh_TW/pokemon-info-container.ts b/src/locales/zh_TW/pokemon-info-container.ts index 068c9ebb431..2d70e769b24 100644 --- a/src/locales/zh_TW/pokemon-info-container.ts +++ b/src/locales/zh_TW/pokemon-info-container.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfoContainer: SimpleTranslationEntries = { "moveset": "Moveset", diff --git a/src/locales/zh_TW/pokemon-info.ts b/src/locales/zh_TW/pokemon-info.ts index b1466033f1a..b3edea0c3d4 100644 --- a/src/locales/zh_TW/pokemon-info.ts +++ b/src/locales/zh_TW/pokemon-info.ts @@ -1,4 +1,4 @@ -import { PokemonInfoTranslationEntries } from "#app/plugins/i18n"; +import { PokemonInfoTranslationEntries } from "#app/interfaces/locales"; export const pokemonInfo: PokemonInfoTranslationEntries = { Stat: { diff --git a/src/locales/zh_TW/pokemon.ts b/src/locales/zh_TW/pokemon.ts index cee85d8905b..7bbbfd6b08c 100644 --- a/src/locales/zh_TW/pokemon.ts +++ b/src/locales/zh_TW/pokemon.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const pokemon: SimpleTranslationEntries = { "bulbasaur": "妙蛙種子", diff --git a/src/locales/zh_TW/save-slot-select-ui-handler.ts b/src/locales/zh_TW/save-slot-select-ui-handler.ts index 98b7764aee2..4a9e02eebee 100644 --- a/src/locales/zh_TW/save-slot-select-ui-handler.ts +++ b/src/locales/zh_TW/save-slot-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const saveSlotSelectUiHandler: SimpleTranslationEntries = { "overwriteData": "Overwrite the data in the selected slot?", diff --git a/src/locales/zh_TW/settings.ts b/src/locales/zh_TW/settings.ts new file mode 100644 index 00000000000..c70a8e0c625 --- /dev/null +++ b/src/locales/zh_TW/settings.ts @@ -0,0 +1,98 @@ +import { SimpleTranslationEntries } from "#app/interfaces/locales.js"; + +export const settings: SimpleTranslationEntries = { + "boy": "男孩", + "girl": "女孩", + "general": "常規", + "display": "顯示", + "audio": "音頻", + "gamepad": "手柄", + "keyboard": "鍵盤", + "gameSpeed": "遊戲速度", + "hpBarSpeed": "血條速度", + "expGainsSpeed": "經驗值獲取動畫速度", + "expPartyDisplay": "顯示隊伍經驗", + "skipSeenDialogues": "跳過已讀對話", + "battleStyle": "對戰模式", + "enableRetries": "允許重試", + "tutorials": "教程", + "touchControls": "觸摸操作", + "vibrations": "手柄震動", + "normal": "普通", + "fast": "快", + "faster": "更快", + "skip": "跳過", + "levelUpNotifications": "升級提示", + "on": "啟用", + "off": "禁用", + "switch": "切換", + "set": "固定", + "auto": "自動", + "disabled": "禁用", + "language": "語言", + "change": "選擇", + "uiTheme": "界面風格", + "default": "默認", + "legacy": "經典", + "windowType": "窗口類型", + "moneyFormat": "金錢格式", + "damageNumbers": "傷害數字", + "simple": "簡單", + "fancy": "華麗", + "abbreviated": "縮寫", + "moveAnimations": "招式動畫", + "showStatsOnLevelUp": "升級時顯示能力值", + "candyUpgradeNotification": "糖果升級提示", + "passivesOnly": "僅被動", + "candyUpgradeDisplay": "糖果升級顯示", + "icon": "圖標", + "animation": "動畫", + "moveInfo": "招式信息", + "showMovesetFlyout": "顯示招式池彈窗", + "showArenaFlyout": "顯示戰場彈窗", + "showTimeOfDayWidget": "顯示時間指示器", + "timeOfDayAnimation": "時間指示器動畫", + "bounce": "彈一下", + "timeOfDay_back": "不彈", + "spriteSet": "寶可夢動畫", + "consistent": "默認", + "mixedAnimated": "全部動畫", + "fusionPaletteSwaps": "融合色調切換", + "playerGender": "玩家性別", + "typeHints": "屬性提示", + "masterVolume": "主音量", + "bgmVolume": "音樂", + "seVolume": "音效", + "musicPreference": "音樂偏好", + "mixed": "全曲混合", + "gamepadPleasePlug": "請連接手柄或按任意鍵", + "delete": "刪除", + "keyboardPleasePress": "請點擊鍵盤上的對應按鍵", + "reset": "重置", + "requireReload": "需要重新加載", + "action": "操作", + "back": "返回", + "pressToBind": "按下以綁定", + "pressButton": "請按鍵……", + "buttonUp": "上", + "buttonDown": "下", + "buttonLeft": "左", + "buttonRight": "右", + "buttonAction": "確認", + "buttonMenu": "菜單", + "buttonSubmit": "提交", + "buttonCancel": "取消", + "buttonStats": "狀態", + "buttonCycleForm": "切換形態", + "buttonCycleShiny": "切換閃光", + "buttonCycleGender": "切換性別", + "buttonCycleAbility": "切換特性", + "buttonCycleNature": "切換性格", + "buttonCycleVariant": "切換變種", + "buttonSpeedUp": "加速", + "buttonSlowDown": "減速", + "alt": " (備用)", + "mute": "靜音", + "controller": "控制器", + "gamepadSupport": "手柄支持" +} as const; diff --git a/src/locales/zh_TW/splash-messages.ts b/src/locales/zh_TW/splash-messages.ts index 496f3c39dc4..3fbbea71564 100644 --- a/src/locales/zh_TW/splash-messages.ts +++ b/src/locales/zh_TW/splash-messages.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const splashMessages: SimpleTranslationEntries = { "battlesWon": "勝利場數!", diff --git a/src/locales/zh_TW/starter-select-ui-handler.ts b/src/locales/zh_TW/starter-select-ui-handler.ts index c28cb39b94b..94ce83956cc 100644 --- a/src/locales/zh_TW/starter-select-ui-handler.ts +++ b/src/locales/zh_TW/starter-select-ui-handler.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The menu namespace holds most miscellaneous text that isn't directly part of the game's @@ -25,7 +25,9 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "addToParty": "加入隊伍", "toggleIVs": "查看個體值", "manageMoves": "管理技能", + "manageNature": "管理性格", "useCandies": "使用糖果", + "selectNature": "選擇性格", "selectMoveSwapOut": "選擇想要替換走的招式", "selectMoveSwapWith": "選擇想要替換成的招式", "unlockPassive": "解鎖被動", diff --git a/src/locales/zh_TW/trainers.ts b/src/locales/zh_TW/trainers.ts index 9a9af64ffb4..6fea28823f3 100644 --- a/src/locales/zh_TW/trainers.ts +++ b/src/locales/zh_TW/trainers.ts @@ -1,4 +1,4 @@ -import {SimpleTranslationEntries} from "#app/plugins/i18n"; +import {SimpleTranslationEntries} from "#app/interfaces/locales"; // Titles of special trainers like gym leaders, elite four, and the champion export const titles: SimpleTranslationEntries = { diff --git a/src/locales/zh_TW/tutorial.ts b/src/locales/zh_TW/tutorial.ts index a97314abec8..482ac5ce651 100644 --- a/src/locales/zh_TW/tutorial.ts +++ b/src/locales/zh_TW/tutorial.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const tutorial: SimpleTranslationEntries = { "intro": `歡迎來到PokéRogue!這是一款以戰鬥爲核心的融合了roguelite元素的寶可夢同人遊戲。 diff --git a/src/locales/zh_TW/voucher.ts b/src/locales/zh_TW/voucher.ts index dd2d4a7891a..9b521e683fd 100644 --- a/src/locales/zh_TW/voucher.ts +++ b/src/locales/zh_TW/voucher.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const voucher: SimpleTranslationEntries = { "vouchers": "兌換券", diff --git a/src/locales/zh_TW/weather.ts b/src/locales/zh_TW/weather.ts index 03f3425aa43..c83e0fdc5bf 100644 --- a/src/locales/zh_TW/weather.ts +++ b/src/locales/zh_TW/weather.ts @@ -1,4 +1,4 @@ -import { SimpleTranslationEntries } from "#app/plugins/i18n"; +import { SimpleTranslationEntries } from "#app/interfaces/locales"; /** * The weather namespace holds text displayed when weather is active during a battle diff --git a/src/messages.ts b/src/messages.ts index b9fbf7f7183..5c465cc08e9 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -1,6 +1,6 @@ import { BattleSpec } from "#enums/battle-spec"; import Pokemon from "./field/pokemon"; -import i18next from "./plugins/i18n"; +import i18next from "i18next"; /** * Builds a message by concatenating the Pokemon name with its potential affix and the given text diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index ac7452ae4c9..7094185eff2 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -18,7 +18,7 @@ import { VoucherType, getVoucherTypeIcon, getVoucherTypeName } from "../system/v import { FormChangeItem, SpeciesFormChangeItemTrigger, pokemonFormChanges } from "../data/pokemon-forms"; import { ModifierTier } from "./modifier-tier"; import { Nature, getNatureName, getNatureStatMultiplier } from "#app/data/nature"; -import i18next from "#app/plugins/i18n"; +import i18next from "i18next"; import { getModifierTierTextTint } from "#app/ui/text"; import * as Overrides from "../overrides"; import { MoneyMultiplierModifier } from "./modifier"; @@ -1017,6 +1017,30 @@ export class EnemyEndureChanceModifierType extends ModifierType { export type ModifierTypeFunc = () => ModifierType; type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: integer) => integer; +/** + * High order function that returns a WeightedModifierTypeWeightFunc that will only be applied on + * classic and skip an ModifierType if current wave is greater or equal to the one passed down + * @param wave - Wave where we should stop showing the modifier + * @param defaultWeight - ModifierType default weight + * @returns A WeightedModifierTypeWeightFunc + */ +function skipInClassicAfterWave(wave: integer, defaultWeight: integer): WeightedModifierTypeWeightFunc { + return (party: Pokemon[]) => { + const gameMode = party[0].scene.gameMode; + const currentWave = party[0].scene.currentBattle.waveIndex; + return gameMode.isClassic && currentWave >= wave ? 0 : defaultWeight; + }; +} + +/** + * High order function that returns a WeightedModifierTypeWeightFunc that will only be applied on + * classic and it will skip a ModifierType if it is the last wave pull. + * @param defaultWeight ModifierType default weight + * @returns A WeightedModifierTypeWeightFunc + */ +function skipInLastClassicWaveOrDefault(defaultWeight: integer) : WeightedModifierTypeWeightFunc { + return skipInClassicAfterWave(199, defaultWeight); +} class WeightedModifierType { public modifierType: ModifierType; public weight: integer | WeightedModifierTypeWeightFunc; @@ -1313,7 +1337,7 @@ const modifierPool: ModifierPool = { }, 3), new WeightedModifierType(modifierTypes.DIRE_HIT, 4), new WeightedModifierType(modifierTypes.SUPER_LURE, 4), - new WeightedModifierType(modifierTypes.NUGGET, 5), + new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)), new WeightedModifierType(modifierTypes.EVOLUTION_ITEM, (party: Pokemon[]) => { return Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15), 8); }, 8), @@ -1336,7 +1360,7 @@ const modifierPool: ModifierPool = { [ModifierTier.ULTRA]: [ new WeightedModifierType(modifierTypes.ULTRA_BALL, 24), new WeightedModifierType(modifierTypes.MAX_LURE, 4), - new WeightedModifierType(modifierTypes.BIG_NUGGET, 12), + new WeightedModifierType(modifierTypes.BIG_NUGGET, skipInLastClassicWaveOrDefault(12)), new WeightedModifierType(modifierTypes.PP_UP, 9), new WeightedModifierType(modifierTypes.PP_MAX, 3), new WeightedModifierType(modifierTypes.MINT, 4), @@ -1371,7 +1395,7 @@ const modifierPool: ModifierPool = { }), [ModifierTier.ROGUE]: [ new WeightedModifierType(modifierTypes.ROGUE_BALL, 24), - new WeightedModifierType(modifierTypes.RELIC_GOLD, 2), + new WeightedModifierType(modifierTypes.RELIC_GOLD, skipInLastClassicWaveOrDefault(2)), new WeightedModifierType(modifierTypes.LEFTOVERS, 3), new WeightedModifierType(modifierTypes.SHELL_BELL, 3), new WeightedModifierType(modifierTypes.BERRY_POUCH, 4), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 5ea983fb598..626d744eef2 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -24,6 +24,9 @@ import * as Overrides from "../overrides"; import { ModifierType, modifierTypes } from "./modifier-type"; import { Command } from "#app/ui/command-ui-handler.js"; +import { allMoves } from "#app/data/move.js"; +import { Abilities } from "#app/enums/abilities.js"; + export type ModifierPredicate = (modifier: Modifier) => boolean; const iconOverflowIndex = 24; @@ -520,6 +523,22 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier { return 1; } + //Applies to items with chance of activating secondary effects ie Kings Rock + getSecondaryChanceMultiplier(pokemon: Pokemon): integer { + // Temporary quickfix to stop game from freezing when the opponet uses u-turn while holding on to king's rock + if (!pokemon.getLastXMoves(0)[0]) { + return 1; + } + const sheerForceAffected = allMoves[pokemon.getLastXMoves(0)[0].move].chance >= 0 && pokemon.hasAbility(Abilities.SHEER_FORCE); + + if (sheerForceAffected) { + return 0; + } else if (pokemon.hasAbility(Abilities.SERENE_GRACE)) { + return 2; + } + return 1; + } + getMaxStackCount(scene: BattleScene, forThreshold?: boolean): integer { const pokemon = this.getPokemon(scene); if (!pokemon) { @@ -831,7 +850,7 @@ export class FlinchChanceModifier extends PokemonHeldItemModifier { const pokemon = args[0] as Pokemon; const flinched = args[1] as Utils.BooleanHolder; - if (!flinched.value && pokemon.randSeedInt(10) < this.getStackCount()) { + if (!flinched.value && pokemon.randSeedInt(10) < (this.getStackCount() * this.getSecondaryChanceMultiplier(pokemon))) { flinched.value = true; return true; } diff --git a/src/phases.ts b/src/phases.ts index a5019ae1f18..e311ab956ac 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,7 +1,7 @@ import BattleScene, { bypassLogin } from "./battle-scene"; import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from "./utils"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr, IncrementMovePriorityAttr } from "./data/move"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr, IncrementMovePriorityAttr } from "./data/move"; import { Mode } from "./ui/ui"; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; @@ -19,14 +19,14 @@ import { biomeLinks, getBiomeName } from "./data/biomes"; import { ModifierTier } from "./modifier/modifier-tier"; import { FusePokemonModifierType, ModifierPoolType, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, RememberMoveModifierType, TmModifierType, getDailyRunStarterModifiers, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptions, getPlayerShopModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { BattlerTagLapseType, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; +import { BattlerTagLapseType, CenterOfAttentionTag, EncoreTag, HideSpriteTag as HiddenTag, ProtectedTag, TrappedTag } from "./data/battler-tags"; import { getPokemonMessage, getPokemonNameWithAffix } from "./messages"; import { Starter } from "./ui/starter-select-ui-handler"; import { Gender } from "./data/gender"; import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather"; import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; -import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, WonderSkinAbAttr, applyPreDefendAbAttrs, FieldPreventMovesAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, WonderSkinAbAttr, applyPreDefendAbAttrs, FieldPreventMovesAbAttr, IgnoreMoveEffectsAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -66,6 +66,7 @@ import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; +const { t } = i18next; export class LoginPhase extends Phase { private showText: boolean; @@ -94,7 +95,14 @@ export class LoginPhase extends Phase { this.scene.playSound("menu_open"); const loadData = () => { - updateUserInfo().then(() => this.scene.gameData.loadSystem().then(() => this.end())); + updateUserInfo().then(success => { + if (!success[0]) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); + return; + } + this.scene.gameData.loadSystem().then(() => this.end()); + }); }; this.scene.ui.setMode(Mode.LOGIN_FORM, { @@ -108,7 +116,14 @@ export class LoginPhase extends Phase { buttonActions: [ () => { this.scene.ui.playSelect(); - updateUserInfo().then(() => this.end()); + updateUserInfo().then(success => { + if (!success[0]) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); + return; + } + this.end(); + } ); }, () => { this.scene.unshiftPhase(new LoginPhase(this.scene, false)); this.end(); @@ -118,6 +133,9 @@ export class LoginPhase extends Phase { } ] }); + } else if (statusCode === 401) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); } else { this.scene.unshiftPhase(new UnavailablePhase(this.scene)); super.end(); @@ -129,7 +147,7 @@ export class LoginPhase extends Phase { this.end(); } else { this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("menu:failedToLoadSaveData")); + this.scene.ui.showText(t("menu:failedToLoadSaveData")); } }); } @@ -184,7 +202,7 @@ export class TitlePhase extends Phase { const options: OptionSelectItem[] = []; if (loggedInUser.lastSessionSlot > -1) { options.push({ - label: i18next.t("menu:continue"), + label: i18next.t("continue", null, { ns: "menu"}), handler: () => { this.loadSaveSlot(this.lastSessionData ? -1 : loggedInUser.lastSessionSlot); return true; @@ -489,7 +507,7 @@ export class SelectGenderPhase extends Phase { this.scene.ui.setMode(Mode.OPTION_SELECT, { options: [ { - label: i18next.t("menu:boy"), + label: i18next.t("settings:boy"), handler: () => { this.scene.gameData.gender = PlayerGender.MALE; this.scene.gameData.saveSetting(SettingKeys.Player_Gender, 0); @@ -498,7 +516,7 @@ export class SelectGenderPhase extends Phase { } }, { - label: i18next.t("menu:girl"), + label: i18next.t("settings:girl"), handler: () => { this.scene.gameData.gender = PlayerGender.FEMALE; this.scene.gameData.saveSetting(SettingKeys.Player_Gender, 1); @@ -628,7 +646,7 @@ export class BattlePhase extends Phase { const tintSprites = this.scene.currentBattle.trainer.getTintSprites(); for (let i = 0; i < sprites.length; i++) { const visible = !trainerSlot || !i === (trainerSlot === TrainerSlot.TRAINER) || sprites.length < 2; - [ sprites[i], tintSprites[i] ].map(sprite => { + [sprites[i], tintSprites[i]].map(sprite => { if (visible) { sprite.x = trainerSlot || sprites.length < 2 ? 0 : i ? 16 : -16; } @@ -925,7 +943,7 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); this.scene.tweens.add({ - targets: [ this.scene.arenaEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.arenaPlayer, this.scene.trainer ].flat(), + targets: [this.scene.arenaEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.arenaPlayer, this.scene.trainer].flat(), x: (_target, _key, value, fieldIndex: integer) => fieldIndex < 2 + (enemyField.length) ? value + 300 : value - 300, duration: 2000, onComplete: () => { @@ -940,21 +958,21 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { - return i18next.t("battle:bossAppeared", {bossName: enemyField[0].name}); + return i18next.t("battle:bossAppeared", { bossName: enemyField[0].name }); } if (this.scene.currentBattle.battleType === BattleType.TRAINER) { if (this.scene.currentBattle.double) { - return i18next.t("battle:trainerAppearedDouble", {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); + return i18next.t("battle:trainerAppearedDouble", { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }); } else { - return i18next.t("battle:trainerAppeared", {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); + return i18next.t("battle:trainerAppeared", { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }); } } return enemyField.length === 1 - ? i18next.t("battle:singleWildAppeared", {pokemonName: enemyField[0].name}) - : i18next.t("battle:multiWildAppeared", {pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name}); + ? i18next.t("battle:singleWildAppeared", { pokemonName: enemyField[0].name }) + : i18next.t("battle:multiWildAppeared", { pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name }); } doEncounterCommon(showEncounterMessage: boolean = true) { @@ -984,7 +1002,7 @@ export class EncounterPhase extends BattlePhase { this.scene.currentBattle.started = true; this.scene.playBgm(undefined); this.scene.pbTray.showPbTray(this.scene.getParty()); - this.scene.pbTrayEnemy.showPbTray(this.scene.getEnemyParty()); + this.scene.pbTrayEnemy.showPbTray(this.scene.getEnemyParty()); const doTrainerSummon = () => { this.hideEnemyTrainer(); const availablePartyMembers = this.scene.getEnemyParty().filter(p => !p.isFainted()).length; @@ -1010,7 +1028,7 @@ export class EncounterPhase extends BattlePhase { this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages), this.scene.currentBattle.waveIndex); const showDialogueAndSummon = () => { - this.scene.ui.showDialogue(message, trainer.getName(TrainerSlot.NONE,true), null, () => { + this.scene.ui.showDialogue(message, trainer.getName(TrainerSlot.NONE, true), null, () => { this.scene.charSprite.hide().then(() => this.scene.hideFieldOverlay(250).then(() => doSummon())); }); }; @@ -1041,7 +1059,7 @@ export class EncounterPhase extends BattlePhase { // how many player pokemon are on the field ? const pokemonsOnFieldCount = this.scene.getParty().filter(p => p.isOnField()).length; // if it's a 2vs1, there will never be a 2nd pokemon on our field even - const requiredPokemonsOnField = Math.min(this.scene.getParty().filter((p) => !p.isFainted()).length, 2); + const requiredPokemonsOnField = Math.min(this.scene.getParty().filter((p) => !p.isFainted()).length, 2); // if it's a double, there should be 2, otherwise 1 if (this.scene.currentBattle.double) { return pokemonsOnFieldCount === requiredPokemonsOnField; @@ -1127,7 +1145,7 @@ export class NextEncounterPhase extends EncounterPhase { const enemyField = this.scene.getEnemyField(); this.scene.tweens.add({ - targets: [ this.scene.arenaEnemy, this.scene.arenaNextEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.lastEnemyTrainer ].flat(), + targets: [this.scene.arenaEnemy, this.scene.arenaNextEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.lastEnemyTrainer].flat(), x: "+=300", duration: 2000, onComplete: () => { @@ -1170,7 +1188,7 @@ export class NewBiomeEncounterPhase extends NextEncounterPhase { const enemyField = this.scene.getEnemyField(); this.scene.tweens.add({ - targets: [ this.scene.arenaEnemy, enemyField ].flat(), + targets: [this.scene.arenaEnemy, enemyField].flat(), x: "+=300", duration: 2000, onComplete: () => { @@ -1236,7 +1254,7 @@ export class SelectBiomePhase extends BattlePhase { let biomeChoices: Biome[]; this.scene.executeWithSeedOffset(() => { biomeChoices = (!Array.isArray(biomeLinks[currentBiome]) - ? [ biomeLinks[currentBiome] as Biome ] + ? [biomeLinks[currentBiome] as Biome] : biomeLinks[currentBiome] as (Biome | [Biome, integer])[]) .filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1])) .map(b => Array.isArray(b) ? b[0] : b); @@ -1291,7 +1309,7 @@ export class SwitchBiomePhase extends BattlePhase { } this.scene.tweens.add({ - targets: [ this.scene.arenaEnemy, this.scene.lastEnemyTrainer ], + targets: [this.scene.arenaEnemy, this.scene.lastEnemyTrainer], x: "+=300", duration: 2000, onComplete: () => { @@ -1309,7 +1327,7 @@ export class SwitchBiomePhase extends BattlePhase { this.scene.arenaPlayerTransition.setVisible(true); this.scene.tweens.add({ - targets: [ this.scene.arenaPlayer, this.scene.arenaBgTransition, this.scene.arenaPlayerTransition ], + targets: [this.scene.arenaPlayer, this.scene.arenaBgTransition, this.scene.arenaPlayerTransition], duration: 1000, delay: 1000, ease: "Sine.easeInOut", @@ -1789,7 +1807,7 @@ export class SummonMissingPhase extends SummonPhase { } preSummon(): void { - this.scene.ui.showText(i18next.t("battle:sendOutPokemon", { pokemonName: this.getPokemon().name})); + this.scene.ui.showText(i18next.t("battle:sendOutPokemon", { pokemonName: this.getPokemon().name })); this.scene.time.delayedCall(250, () => this.summon()); } } @@ -1821,7 +1839,7 @@ export class TurnInitPhase extends FieldPhase { this.scene.getPlayerField().forEach(p => { // If this pokemon is in play and evolved into something illegal under the current challenge, force a switch if (p.isOnField() && !p.isAllowedInBattle()) { - this.scene.queueMessage(i18next.t("challenges:illegalEvolution", {"pokemon": p.name}), null, true); + this.scene.queueMessage(i18next.t("challenges:illegalEvolution", { "pokemon": p.name }), null, true); const allowedPokemon = this.scene.getParty().filter(p => p.isAllowedInBattle()); @@ -1902,7 +1920,7 @@ export class CommandPhase extends FieldPhase { while (moveQueue.length && moveQueue[0] && moveQueue[0].move && (!playerPokemon.getMoveset().find(m => m.moveId === moveQueue[0].move) - || !playerPokemon.getMoveset()[playerPokemon.getMoveset().findIndex(m => m.moveId === moveQueue[0].move)].isUsable(playerPokemon, moveQueue[0].ignorePP))) { + || !playerPokemon.getMoveset()[playerPokemon.getMoveset().findIndex(m => m.moveId === moveQueue[0].move)].isUsable(playerPokemon, moveQueue[0].ignorePP))) { moveQueue.shift(); } @@ -1932,13 +1950,13 @@ export class CommandPhase extends FieldPhase { case Command.FIGHT: let useStruggle = false; if (cursor === -1 || - playerPokemon.trySelectMove(cursor, args[0] as boolean) || - (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) { + playerPokemon.trySelectMove(cursor, args[0] as boolean) || + (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) { const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor].moveId : Moves.NONE : Moves.STRUGGLE; const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args }; const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, moveId) : args[2]; if (!moveId) { - turnCommand.targets = [ this.fieldIndex ]; + turnCommand.targets = [this.fieldIndex]; } console.log(moveTargets, playerPokemon.name); if (moveTargets.targets.length <= 1 || moveTargets.multiple) { @@ -2159,7 +2177,7 @@ export class EnemyCommandPhase extends FieldPhase { const index = trainer.getNextSummonIndex(enemyPokemon.trainerSlot, partyMemberScores); battle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] = - { command: Command.POKEMON, cursor: index, args: [ false ] }; + { command: Command.POKEMON, cursor: index, args: [false] }; battle.enemySwitchCounter++; @@ -2196,7 +2214,7 @@ export class SelectTargetPhase extends PokemonPhase { this.scene.currentBattle.turnCommands[this.fieldIndex] = null; this.scene.unshiftPhase(new CommandPhase(this.scene, this.fieldIndex)); } else { - turnCommand.targets = [ cursor ]; + turnCommand.targets = [cursor]; } if (turnCommand.command === Command.BALL && this.fieldIndex) { this.scene.currentBattle.turnCommands[this.fieldIndex - 1].skip = true; @@ -2244,10 +2262,10 @@ export class TurnStartPhase extends FieldPhase { const aPriority = new Utils.IntegerHolder(aMove.priority); const bPriority = new Utils.IntegerHolder(bMove.priority); - applyMoveAttrs(IncrementMovePriorityAttr,this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a),null,aMove,aPriority); - applyMoveAttrs(IncrementMovePriorityAttr,this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b),null,bMove,bPriority); + applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, aMove, aPriority); + applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b), null, bMove, bPriority); - applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, aMove, aPriority); + applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a), null, aMove, aPriority); applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b), null, bMove, bPriority); if (aPriority.value !== bPriority.value) { @@ -2308,7 +2326,7 @@ export class TurnStartPhase extends FieldPhase { return; } }); - // if only one pokemon is alive, use that one + // if only one pokemon is alive, use that one if (playerActivePokemon.length > 1) { // find which active pokemon has faster speed const fasterPokemon = playerActivePokemon[0].getStat(Stat.SPD) > playerActivePokemon[1].getStat(Stat.SPD) ? playerActivePokemon[0] : playerActivePokemon[1]; @@ -2564,6 +2582,11 @@ export class MovePhase extends BattlePhase { if (this.move.moveId && this.pokemon.summonData?.disabledMove === this.move.moveId) { this.scene.queueMessage(`${this.move.getName()} is disabled!`); } + if (this.move.ppUsed >= this.move.getMovePp()) { // if the move PP was reduced from Spite or otherwise, the move fails + this.fail(); + this.showMoveText(); + this.showFailedText(); + } return this.end(); } @@ -2583,6 +2606,12 @@ export class MovePhase extends BattlePhase { if (moveTarget) { const oldTarget = moveTarget.value; this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget)); + this.pokemon.getOpponents().forEach(p => { + const redirectTag = p.getTag(CenterOfAttentionTag) as CenterOfAttentionTag; + if (redirectTag && (!redirectTag.powder || (!this.pokemon.isOfType(Type.GRASS) && !this.pokemon.hasAbility(Abilities.OVERCOAT)))) { + moveTarget.value = p.getBattlerIndex(); + } + }); //Check if this move is immune to being redirected, and restore its target to the intended target if it is. if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) || this.move.getMove().hasAttr(BypassRedirectAttr))) { //If an ability prevented this move from being redirected, display its ability pop up. @@ -2590,7 +2619,7 @@ export class MovePhase extends BattlePhase { this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr))); } moveTarget.value = oldTarget; - } + } this.targets[0] = moveTarget.value; } @@ -2817,7 +2846,7 @@ export class MoveEffectPhase extends PokemonPhase { // of the left Pokemon and gets hit unless this is checked. if (targets.includes(battlerIndex) && this.move.getMove().moveTarget === MoveTarget.ALL_NEAR_OTHERS) { const i = targets.indexOf(battlerIndex); - targets.splice(i,i+1); + targets.splice(i, i + 1); } this.targets = targets; } @@ -2857,7 +2886,7 @@ export class MoveEffectPhase extends PokemonPhase { const moveHistoryEntry = { move: this.move.moveId, targets: this.targets, result: MoveResult.PENDING, virtual: this.move.virtual }; user.pushMoveHistory(moveHistoryEntry); - const targetHitChecks = Object.fromEntries(targets.map(p => [ p.getBattlerIndex(), this.hitCheck(p) ])); + const targetHitChecks = Object.fromEntries(targets.map(p => [p.getBattlerIndex(), this.hitCheck(p)])); const activeTargets = targets.map(t => t.isActive(true)); if (!activeTargets.length || (!move.hasAttr(VariableTargetAttr) && !move.isMultiTarget() && !targetHitChecks[this.targets[0]])) { user.turnData.hitCount = 1; @@ -2917,26 +2946,26 @@ export class MoveEffectPhase extends PokemonPhase { const chargeEffect = !!move.getAttrs(ChargeAttr).find(ca => ca.usedChargeEffect(user, this.getTarget(), move)); // Charge attribute with charge effect takes all effect attributes and applies them to charge stage, so ignore them if this is present Utils.executeIf(!chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_APPLY - && attr.selfTarget && (!attr.firstHitOnly || firstHit), user, target, move)).then(() => { + && attr.selfTarget && (!attr.firstHitOnly || firstHit), user, target, move)).then(() => { if (hitResult !== HitResult.NO_EFFECT) { - applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.POST_APPLY - && !attr.selfTarget && (!attr.firstHitOnly || firstHit), user, target, move).then(() => { - if (hitResult < HitResult.NO_EFFECT) { + applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_APPLY + && !(attr as MoveEffectAttr).selfTarget && (!attr.firstHitOnly || firstHit), user, target, this.move.getMove()).then(() => { + if (hitResult < HitResult.NO_EFFECT && !target.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr)) { const flinched = new Utils.BooleanHolder(false); user.scene.applyModifiers(FlinchChanceModifier, user.isPlayer(), user, flinched); if (flinched.value) { target.addTag(BattlerTagType.FLINCHED, undefined, this.move.moveId, user.id); } } - Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && attr.trigger === MoveEffectTrigger.HIT && (!attr.firstHitOnly || firstHit), - user, target, move).then(() => { - return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, move, hitResult).then(() => { - if (!user.isPlayer() && move instanceof AttackMove) { + Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT && (!attr.firstHitOnly || firstHit), + user, target, this.move.getMove()).then(() => { + return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move.getMove(), hitResult).then(() => { + if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) { user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target); } })).then(() => { - applyPostAttackAbAttrs(PostAttackAbAttr, user, target, move, hitResult).then(() => { - if (move instanceof AttackMove) { + applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move.getMove(), hitResult).then(() => { + if (this.move.getMove() instanceof AttackMove) { this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target.getFieldIndex()); } resolve(); @@ -3133,7 +3162,7 @@ export class MoveAnimTestPhase extends BattlePhase { } initMoveAnim(this.scene, moveId).then(() => { - loadMoveAnimAssets(this.scene, [ moveId ], true) + loadMoveAnimAssets(this.scene, [moveId], true) .then(() => { new MoveAnim(moveId, player ? this.scene.getPlayerPokemon() : this.scene.getEnemyPokemon(), (player !== (allMoves[moveId] instanceof SelfStatusMove) ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon()).getBattlerIndex()).play(this.scene, () => { if (player) { @@ -3310,7 +3339,7 @@ export class StatChangePhase extends PokemonPhase { } aggregateStatChanges(random: boolean = false): void { - const isAccEva = [ BattleStat.ACC, BattleStat.EVA ].some(s => this.stats.includes(s)); + const isAccEva = [BattleStat.ACC, BattleStat.EVA].some(s => this.stats.includes(s)); let existingPhase: StatChangePhase; if (this.stats.length === 1) { while ((existingPhase = (this.scene.findPhase(p => p instanceof StatChangePhase && p.battlerIndex === this.battlerIndex && p.stats.length === 1 @@ -3330,7 +3359,7 @@ export class StatChangePhase extends PokemonPhase { } } while ((existingPhase = (this.scene.findPhase(p => p instanceof StatChangePhase && p.battlerIndex === this.battlerIndex && p.selfTarget === this.selfTarget - && ([ BattleStat.ACC, BattleStat.EVA ].some(s => p.stats.includes(s)) === isAccEva) + && ([BattleStat.ACC, BattleStat.EVA].some(s => p.stats.includes(s)) === isAccEva) && p.levels === this.levels && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatChangePhase))) { this.stats.push(...existingPhase.stats); if (!this.scene.tryRemovePhase(p => p === existingPhase)) { @@ -3494,7 +3523,7 @@ export class PostTurnStatusEffectPhase extends PokemonPhase { break; } if (damage) { - // Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ... + // Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ... this.scene.damageNumberHandler.add(this.getPokemon(), pokemon.damage(damage, false, true)); pokemon.updateInfo(); } @@ -3944,7 +3973,7 @@ export class TrainerVictoryPhase extends BattlePhase { const trainerType = this.scene.currentBattle.trainer.config.trainerType; if (vouchers.hasOwnProperty(TrainerType[trainerType])) { if (!this.scene.validateVoucher(vouchers[TrainerType[trainerType]]) && this.scene.currentBattle.trainer.config.isBoss) { - this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); + this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM][vouchers[TrainerType[trainerType]].voucherType])); } } @@ -4209,7 +4238,8 @@ export class GameOverPhase extends BattlePhase { If Offline, execute offlineNewClear(), a localStorage implementation of newClear daily run checks */ if (this.victory) { if (!Utils.isLocal) { - Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true) .then(response => response.json()) + Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true) + .then(response => response.json()) .then(newClear => doGameOver(newClear)); } else { this.scene.gameData.offlineNewClear(this.scene).then(result => { @@ -4552,7 +4582,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { if (emptyMoveIndex > -1) { pokemon.setMove(emptyMoveIndex, this.moveId); initMoveAnim(this.scene, this.moveId).then(() => { - loadMoveAnimAssets(this.scene, [ this.moveId ], true) + loadMoveAnimAssets(this.scene, [this.moveId], true) .then(() => { this.scene.ui.setMode(messageMode).then(() => { this.scene.playSound("level_up_fanfare"); @@ -4925,7 +4955,7 @@ export class AttemptCapturePhase extends PokemonPhase { } }); }; - Promise.all([ pokemon.hideInfo(), this.scene.gameData.setPokemonCaught(pokemon) ]).then(() => { + Promise.all([pokemon.hideInfo(), this.scene.gameData.setPokemonCaught(pokemon)]).then(() => { if (this.scene.getParty().length === 6) { const promptRelease = () => { this.scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: pokemon.name }), null, () => { @@ -4989,7 +5019,7 @@ export class AttemptRunPhase extends PokemonPhase { this.scene.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500); this.scene.tweens.add({ - targets: [ this.scene.arenaEnemy, enemyField ].flat(), + targets: [this.scene.arenaEnemy, enemyField].flat(), alpha: 0, duration: 250, ease: "Sine.easeIn", @@ -5078,7 +5108,7 @@ export class SelectModifierPhase extends BattlePhase { this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => { if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier - && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; + && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; const itemModifier = itemModifiers[itemIndex]; this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity); } else { @@ -5204,7 +5234,7 @@ export class SelectModifierPhase extends BattlePhase { getRerollCost(typeOptions: ModifierTypeOption[], lockRarities: boolean): integer { let baseValue = 0; if (lockRarities) { - const tierValues = [ 50, 125, 300, 750, 2000 ]; + const tierValues = [50, 125, 300, 750, 2000]; for (const opt of typeOptions) { baseValue += tierValues[opt.type.tier]; } @@ -5424,7 +5454,7 @@ export class TrainerMessageTestPhase extends BattlePhase { continue; } const config = trainerConfigs[type]; - [ config.encounterMessages, config.femaleEncounterMessages, config.victoryMessages, config.femaleVictoryMessages, config.defeatMessages, config.femaleDefeatMessages ] + [config.encounterMessages, config.femaleEncounterMessages, config.victoryMessages, config.femaleVictoryMessages, config.defeatMessages, config.femaleDefeatMessages] .map(messages => { if (messages?.length) { testMessages.push(...messages); diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 9bd288cd676..14e5c74f12c 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -12,83 +12,6 @@ import { ptBrConfig } from "#app/locales/pt_BR/config.js"; import { zhCnConfig } from "#app/locales/zh_CN/config.js"; import { zhTwConfig } from "#app/locales/zh_TW/config.js"; -export interface SimpleTranslationEntries { - [key: string]: string -} - -export interface MoveTranslationEntry { - name: string, - effect: string -} - -export interface MoveTranslationEntries { - [key: string]: MoveTranslationEntry -} - -export interface AbilityTranslationEntry { - name: string, - description: string -} - -export interface AbilityTranslationEntries { - [key: string]: AbilityTranslationEntry -} - -export interface ModifierTypeTranslationEntry { - name?: string, - description?: string, - extra?: SimpleTranslationEntries -} - -export interface ModifierTypeTranslationEntries { - ModifierType: { [key: string]: ModifierTypeTranslationEntry }, - AttackTypeBoosterItem: SimpleTranslationEntries, - TempBattleStatBoosterItem: SimpleTranslationEntries, - TempBattleStatBoosterStatName: SimpleTranslationEntries, - BaseStatBoosterItem: SimpleTranslationEntries, - EvolutionItem: SimpleTranslationEntries, - FormChangeItem: SimpleTranslationEntries, -} -export interface PokemonInfoTranslationEntries { - Stat: SimpleTranslationEntries, - Type: SimpleTranslationEntries, -} - -export interface BerryTranslationEntry { - name: string, - effect: string, -} - -export interface BerryTranslationEntries { - [key: string]: BerryTranslationEntry -} - -export interface AchievementTranslationEntry { - name?: string, - description?: string, -} - -export interface AchievementTranslationEntries { - [key: string]: AchievementTranslationEntry; -} - -export interface DialogueTranslationEntry { - [key: number]: string; -} - -export interface DialogueTranslationCategory { - [category: string]: DialogueTranslationEntry; -} - -export interface DialogueTranslationEntries { - [trainertype: string]: DialogueTranslationCategory; -} - - -export interface Localizable { - localize(): void; -} - const fonts = [ new FontFace("emerald", "url(./fonts/PokePT_Wansung.ttf)", { unicodeRange: "U+AC00-D7AC"}), Object.assign( @@ -125,7 +48,8 @@ export async function initI18n(): Promise { * * Q: How do I add a new namespace? * A: To add a new namespace, create a new file in each language folder with the translations. - * Then update the `resources` field in the init() call and the CustomTypeOptions interface. + * Then update the config file for that language in its locale directory + * and the CustomTypeOptions interface in the @types/i18next.d.ts file. * * Q: How do I make a language selectable in the settings? * A: In src/system/settings.ts, add a new case to the Setting.Language switch statement. @@ -138,6 +62,8 @@ export async function initI18n(): Promise { nonExplicitSupportedLngs: true, fallbackLng: "en", supportedLngs: ["en", "es", "fr", "it", "de", "zh", "pt", "ko"], + defaultNS: "menu", + ns: Object.keys(enConfig), detection: { lookupLocalStorage: "prLang" }, @@ -180,59 +106,6 @@ export async function initI18n(): Promise { await initFonts(); } -// Module declared to make referencing keys in the localization files type-safe. -declare module "i18next" { - interface CustomTypeOptions { - defaultNS: "menu"; // Even if we don't use it, i18next requires a valid default namespace - resources: { - ability: AbilityTranslationEntries; - abilityTriggers: SimpleTranslationEntries; - achv: AchievementTranslationEntries; - battle: SimpleTranslationEntries; - battleMessageUiHandler: SimpleTranslationEntries; - berry: BerryTranslationEntries; - biome: SimpleTranslationEntries; - challenges: SimpleTranslationEntries; - commandUiHandler: SimpleTranslationEntries; - PGMachv: AchievementTranslationEntries; - PGMdialogue: DialogueTranslationEntries; - PGMbattleSpecDialogue: SimpleTranslationEntries; - PGMmiscDialogue: SimpleTranslationEntries; - PGMdoubleBattleDialogue: DialogueTranslationEntries; - PGFdialogue: DialogueTranslationEntries; - PGFbattleSpecDialogue: SimpleTranslationEntries; - PGFmiscDialogue: SimpleTranslationEntries; - PGFdoubleBattleDialogue: DialogueTranslationEntries; - PGFachv: AchievementTranslationEntries; - egg: SimpleTranslationEntries; - fightUiHandler: SimpleTranslationEntries; - gameMode: SimpleTranslationEntries; - gameStatsUiHandler: SimpleTranslationEntries; - growth: SimpleTranslationEntries; - menu: SimpleTranslationEntries; - menuUiHandler: SimpleTranslationEntries; - modifierType: ModifierTypeTranslationEntries; - move: MoveTranslationEntries; - nature: SimpleTranslationEntries; - partyUiHandler: SimpleTranslationEntries; - pokeball: SimpleTranslationEntries; - pokemon: SimpleTranslationEntries; - pokemonInfo: PokemonInfoTranslationEntries; - pokemonInfoContainer: SimpleTranslationEntries; - saveSlotSelectUiHandler: SimpleTranslationEntries; - splashMessages: SimpleTranslationEntries; - starterSelectUiHandler: SimpleTranslationEntries; - titles: SimpleTranslationEntries; - trainerClasses: SimpleTranslationEntries; - trainerNames: SimpleTranslationEntries; - tutorial: SimpleTranslationEntries; - voucher: SimpleTranslationEntries; - weather: SimpleTranslationEntries; - battleStat: SimpleTranslationEntries; - }; - } -} - export default i18next; export function getIsInitialized(): boolean { diff --git a/src/system/achv.ts b/src/system/achv.ts index 21393862d92..511ddd1eb8e 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -1,7 +1,7 @@ import { Modifier } from "typescript"; import BattleScene from "../battle-scene"; import { TurnHeldItemTransferModifier } from "../modifier/modifier"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import * as Utils from "../utils"; import { PlayerGender } from "#enums/player-gender"; import { ParseKeys } from "i18next"; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 9fb253df092..f36bf1af229 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -136,7 +136,7 @@ interface VoucherUnlocks { } export interface VoucherCounts { - [type: string]: integer; + [type: string]: integer; } export interface DexData { @@ -187,6 +187,46 @@ export interface StarterMoveData { [key: integer]: StarterMoveset | StarterFormMoveData } +export interface StarterAttributes { + nature?: integer; + ability?: integer; + variant?: integer; + form?: integer; + female?: boolean; +} + +export interface StarterPreferences { + [key: integer]: StarterAttributes; +} + +// the latest data saved/loaded for the Starter Preferences. Required to reduce read/writes. Initialize as "{}", since this is the default value and no data needs to be stored if present. +// if they ever add private static variables, move this into StarterPrefs +const StarterPrefers_DEFAULT : string = "{}"; +let StarterPrefers_private_latest : string = StarterPrefers_DEFAULT; + +// This is its own class as StarterPreferences... +// - don't need to be loaded on startup +// - isn't stored with other data +// - don't require to be encrypted +// - shouldn't require calls outside of the starter selection +export class StarterPrefs { + // called on starter selection show once + static load(): StarterPreferences { + return JSON.parse( + StarterPrefers_private_latest = (localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT) + ); + } + + // called on starter selection clear, always + static save(prefs: StarterPreferences): void { + const pStr : string = JSON.stringify(prefs); + if (pStr !== StarterPrefers_private_latest) { + // something changed, store the update + localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr); + } + } +} + export interface StarterDataEntry { moveset: StarterMoveset | StarterFormMoveData; eggMoves: integer; @@ -1261,7 +1301,7 @@ export class GameData { if (!bypassLogin && dataType < GameDataType.SETTINGS) { updateUserInfo().then(success => { - if (!success) { + if (!success[0]) { return displayError(`Could not contact the server. Your ${dataName} data could not be imported.`); } let url: string; diff --git a/src/system/settings/settings-keyboard.ts b/src/system/settings/settings-keyboard.ts index 662c718ddcc..d60af06e12b 100644 --- a/src/system/settings/settings-keyboard.ts +++ b/src/system/settings/settings-keyboard.ts @@ -2,6 +2,7 @@ import {Button} from "#enums/buttons"; import BattleScene from "#app/battle-scene"; import {Mode} from "#app/ui/ui"; import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler"; +import i18next from "i18next"; export enum SettingKeyboard { // Default_Layout = "DEFAULT_LAYOUT", @@ -41,7 +42,7 @@ export enum SettingKeyboard { Alt_Button_Submit = "ALT_BUTTON_SUBMIT", } -const pressAction = "Press action to assign"; +const pressAction = i18next.t("settings:pressToBind"); export const settingKeyboardOptions = { // [SettingKeyboard.Default_Layout]: ['Default'], diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index b929e8ad1e8..1cc525b0bac 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -9,10 +9,33 @@ import { EaseType } from "#enums/ease-type"; import { MoneyFormat } from "#enums/money-format"; import { PlayerGender } from "#enums/player-gender"; -const MUTE = "Mute"; -const VOLUME_OPTIONS = new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : MUTE); -const OFF_ON = ["Off", "On"]; -const AUTO_DISABLED = ["Auto", "Disabled"]; +const VOLUME_OPTIONS: SettingOption[] = new Array(11).fill(null).map((_, i) => i ? { + value: (i * 10).toString(), + label: (i * 10).toString(), +} : { + value: "Mute", + label: i18next.t("settings:mute") +}); +const OFF_ON: SettingOption[] = [ + { + value: "Off", + label: i18next.t("settings:off") + }, + { + value: "On", + label: i18next.t("settings:on") + } +]; +const AUTO_DISABLED: SettingOption[] = [ + { + value: "Auto", + label: i18next.t("settings:auto") + }, + { + value: "Disabled", + label: i18next.t("settings:disabled") + } +]; /** * Types for helping separate settings to different menus @@ -23,10 +46,15 @@ export enum SettingType { AUDIO } +type SettingOption = { + value: string, + label: string +}; + export interface Setting { key: string label: string - options: Array + options: SettingOption[] default: number type: SettingType requireReload?: boolean @@ -77,164 +105,321 @@ export const SettingKeys = { export const Setting: Array = [ { key: SettingKeys.Game_Speed, - label: "Game Speed", - options: ["1x", "1.25x", "1.5x", "2x", "2.5x", "3x", "4x", "5x"], + label: i18next.t("settings:gameSpeed"), + options: [ + { + value: "1", + label: "1x" + }, + { + value: "1.25", + label: "1.25x" + }, + { + value: "1.5", + label: "1.5x" + }, + { + value: "2", + label: "2x" + }, + { + value: "2.5", + label: "2.5x" + }, + { + value: "3", + label: "3x" + }, + { + value: "4", + label: "4x" + }, + { + value: "5", + label: "5x" + } + ], default: 3, type: SettingType.GENERAL }, { key: SettingKeys.HP_Bar_Speed, - label: "HP Bar Speed", - options: ["Normal", "Fast", "Faster", "Skip"], + label: i18next.t("settings:hpBarSpeed"), + options: [ + { + value: "Normal", + label: i18next.t("settings:normal") + }, + { + value: "Fast", + label: i18next.t("settings:fast") + }, + { + value: "Faster", + label: i18next.t("settings:faster") + }, + { + value: "Skip", + label: i18next.t("settings:skip") + } + ], default: 0, type: SettingType.GENERAL }, { key: SettingKeys.EXP_Gains_Speed, - label: "EXP Gains Speed", - options: ["Normal", "Fast", "Faster", "Skip"], + label: i18next.t("settings:expGainsSpeed"), + options: [ + { + value: "Normal", + label: i18next.t("settings:normal") + }, + { + value: "Fast", + label: i18next.t("settings:fast") + }, + { + value: "Faster", + label: i18next.t("settings:faster") + }, + { + value: "Skip", + label: i18next.t("settings:skip") + } + ], default: 0, type: SettingType.GENERAL }, { key: SettingKeys.EXP_Party_Display, - label: "EXP Party Display", - options: ["Normal", "Level Up Notification", "Skip"], + label: i18next.t("settings:expPartyDisplay"), + options: [ + { + value: "Normal", + label: i18next.t("settings:normal") + }, + { + value: "Level Up Notification", + label: i18next.t("settings:levelUpNotifications") + }, + { + value: "Skip", + label: i18next.t("settings:skip") + } + ], default: 0, type: SettingType.GENERAL }, { key: SettingKeys.Skip_Seen_Dialogues, - label: "Skip Seen Dialogues", + label: i18next.t("settings:skipSeenDialogues"), options: OFF_ON, default: 0, type: SettingType.GENERAL }, { key: SettingKeys.Battle_Style, - label: "Battle Style", - options: ["Switch", "Set"], + label: i18next.t("settings:battleStyle"), + options: [ + { + value: "Switch", + label: i18next.t("settings:switch") + }, + { + value: "Set", + label: i18next.t("settings:set") + } + ], default: 0, type: SettingType.GENERAL }, { key: SettingKeys.Enable_Retries, - label: "Enable Retries", + label: i18next.t("settings:enableRetries"), options: OFF_ON, default: 0, type: SettingType.GENERAL }, { key: SettingKeys.Tutorials, - label: "Tutorials", + label: i18next.t("settings:tutorials"), options: OFF_ON, default: 1, type: SettingType.GENERAL }, { key: SettingKeys.Touch_Controls, - label: "Touch Controls", + label: i18next.t("settings:touchControls"), options: AUTO_DISABLED, default: 0, type: SettingType.GENERAL }, { key: SettingKeys.Vibration, - label: "Vibration", + label: i18next.t("settings:vibrations"), options: AUTO_DISABLED, default: 0, type: SettingType.GENERAL }, { key: SettingKeys.Language, - label: "Language", - options: ["English", "Change"], + label: i18next.t("settings:language"), + options: [ + { + value: "English", + label: "English" + }, + { + value: "Change", + label: i18next.t("settings:change") + } + ], default: 0, type: SettingType.DISPLAY, requireReload: true }, { key: SettingKeys.UI_Theme, - label: "UI Theme", - options: ["Default", "Legacy"], + label: i18next.t("settings:uiTheme"), + options: [ + { + value: "Default", + label: i18next.t("settings:default") + }, + { + value: "Legacy", + label: i18next.t("settings:legacy") + } + ], default: 0, type: SettingType.DISPLAY, requireReload: true }, { key: SettingKeys.Window_Type, - label: "Window Type", - options: new Array(5).fill(null).map((_, i) => (i + 1).toString()), + label: i18next.t("settings:windowType"), + options: new Array(5).fill(null).map((_, i) => { + const windowType = (i + 1).toString(); + return { + value: windowType, + label: windowType + }; + }), default: 0, type: SettingType.DISPLAY }, { key: SettingKeys.Money_Format, - label: "Money Format", - options: ["Normal", "Abbreviated"], + label: i18next.t("settings:moneyFormat"), + options: [ + { + value: "Normal", + label: i18next.t("settings:normal") + }, + { + value: "Abbreviated", + label: i18next.t("settings:abbreviated") + } + ], default: 0, type: SettingType.DISPLAY }, { key: SettingKeys.Damage_Numbers, - label: "Damage Numbers", - options: ["Off", "Simple", "Fancy"], + label: i18next.t("settings:damageNumbers"), + options: [ + { + value: "Off", + label: i18next.t("settings:off") + }, + { + value: "Simple", + label: i18next.t("settings:simple") + }, + { + value: "Fancy", + label: i18next.t("settings:fancy") + } + ], default: 0, type: SettingType.DISPLAY }, { key: SettingKeys.Move_Animations, - label: "Move Animations", + label: i18next.t("settings:moveAnimations"), options: OFF_ON, default: 1, type: SettingType.DISPLAY }, { key: SettingKeys.Show_Stats_on_Level_Up, - label: "Show Stats on Level Up", + label: i18next.t("settings:showStatsOnLevelUp"), options: OFF_ON, default: 1, type: SettingType.DISPLAY }, { key: SettingKeys.Candy_Upgrade_Notification, - label: "Candy Upgrade Notification", - options: ["Off", "Passives Only", "On"], + label: i18next.t("settings:candyUpgradeNotification"), + options: [ + { + value: "Off", + label: i18next.t("settings:off") + }, + { + value: "Passives Only", + label: i18next.t("settings:passivesOnly") + }, + { + value: "On", + label: i18next.t("settings:on") + } + ], default: 0, type: SettingType.DISPLAY }, { key: SettingKeys.Candy_Upgrade_Display, - label: "Candy Upgrade Display", - options: ["Icon", "Animation"], + label: i18next.t("settings:candyUpgradeDisplay"), + options: [ + { + value: "Icon", + label: i18next.t("settings:icon") + }, + { + value: "Animation", + label: i18next.t("settings:animation") + } + ], default: 0, type: SettingType.DISPLAY, requireReload: true }, { key: SettingKeys.Move_Info, - label: "Move Info", + label: i18next.t("settings:moveInfo"), options: OFF_ON, default: 1, type: SettingType.DISPLAY }, { key: SettingKeys.Show_Moveset_Flyout, - label: "Show Moveset Flyout", + label: i18next.t("settings:showMovesetFlyout"), options: OFF_ON, default: 1, type: SettingType.DISPLAY }, { key: SettingKeys.Show_Arena_Flyout, - label: "Show Battle Effects Flyout", + label: i18next.t("settings:showArenaFlyout"), options: OFF_ON, default: 1, type: SettingType.DISPLAY }, { key: SettingKeys.Show_Time_Of_Day_Widget, - label: "Show Time of Day Widget", + label: i18next.t("settings:showTimeOfDayWidget"), options: OFF_ON, default: 1, type: SettingType.DISPLAY, @@ -242,65 +427,101 @@ export const Setting: Array = [ }, { key: SettingKeys.Time_Of_Day_Animation, - label: "Time of Day Animation", - options: ["Bounce", "Back"], + label: i18next.t("settings:timeOfDayAnimation"), + options: [ + { + value: "Bounce", + label: i18next.t("settings:bounce") + }, + { + value: "Back", + label: i18next.t("settings:timeOfDay_back") + } + ], default: 0, type: SettingType.DISPLAY }, { key: SettingKeys.Sprite_Set, - label: "Sprite Set", - options: ["Consistent", "Mixed Animated"], + label: i18next.t("settings:spriteSet"), + options: [ + { + value: "Consistent", + label: i18next.t("settings:consistent") + }, + { + value: "Mixed Animated", + label: i18next.t("settings:mixedAnimated") + } + ], default: 0, type: SettingType.DISPLAY, requireReload: true }, { key: SettingKeys.Fusion_Palette_Swaps, - label: "Fusion Palette Swaps", + label: i18next.t("settings:fusionPaletteSwaps"), options: OFF_ON, default: 1, type: SettingType.DISPLAY }, { key: SettingKeys.Player_Gender, - label: "Player Gender", - options: ["Boy", "Girl"], + label: i18next.t("settings:playerGender"), + options: [ + { + value: "Boy", + label: i18next.t("settings:boy") + }, + { + value: "Girl", + label: i18next.t("settings:girl") + } + ], default: 0, type: SettingType.DISPLAY }, { key: SettingKeys.Type_Hints, - label: "Type hints", + label: i18next.t("settings:typeHints"), options: OFF_ON, default: 0, type: SettingType.DISPLAY }, { key: SettingKeys.Master_Volume, - label: "Master Volume", + label: i18next.t("settings:masterVolume"), options: VOLUME_OPTIONS, default: 5, type: SettingType.AUDIO }, { key: SettingKeys.BGM_Volume, - label: "BGM Volume", + label: i18next.t("settings:bgmVolume"), options: VOLUME_OPTIONS, default: 10, type: SettingType.AUDIO }, { key: SettingKeys.SE_Volume, - label: "SE Volume", + label: i18next.t("settings:seVolume"), options: VOLUME_OPTIONS, default: 10, type: SettingType.AUDIO }, { key: SettingKeys.Music_Preference, - label: "Music Preference", - options: ["Consistent", "Mixed"], + label: i18next.t("settings:musicPreference"), + options: [ + { + value: "Consistent", + label: i18next.t("settings:consistent") + }, + { + value: "Mixed", + label: i18next.t("settings:mixed") + } + ], default: 0, type: SettingType.AUDIO, requireReload: true @@ -333,23 +554,23 @@ export function resetSettings(scene: BattleScene) { */ export function setSetting(scene: BattleScene, setting: string, value: integer): boolean { const index: number = settingIndex(setting); - if ( index === -1) { + if (index === -1) { return false; } switch (Setting[index].key) { case SettingKeys.Game_Speed: - scene.gameSpeed = parseFloat(Setting[index].options[value].replace("x", "")); + scene.gameSpeed = parseFloat(Setting[index].options[value].value.replace("x", "")); break; case SettingKeys.Master_Volume: - scene.masterVolume = value ? parseInt(Setting[index].options[value]) * 0.01 : 0; + scene.masterVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; scene.updateSoundVolume(); break; case SettingKeys.BGM_Volume: - scene.bgmVolume = value ? parseInt(Setting[index].options[value]) * 0.01 : 0; + scene.bgmVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; scene.updateSoundVolume(); break; case SettingKeys.SE_Volume: - scene.seVolume = value ? parseInt(Setting[index].options[value]) * 0.01 : 0; + scene.seVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; scene.updateSoundVolume(); break; case SettingKeys.Music_Preference: @@ -362,19 +583,19 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): scene.uiTheme = value; break; case SettingKeys.Window_Type: - updateWindowType(scene, parseInt(Setting[index].options[value])); + updateWindowType(scene, parseInt(Setting[index].options[value].value)); break; case SettingKeys.Tutorials: - scene.enableTutorials = Setting[index].options[value] === "On"; + scene.enableTutorials = Setting[index].options[value].value === "On"; break; case SettingKeys.Move_Info: - scene.enableMoveInfo = Setting[index].options[value] === "On"; + scene.enableMoveInfo = Setting[index].options[value].value === "On"; break; case SettingKeys.Enable_Retries: - scene.enableRetries = Setting[index].options[value] === "On"; + scene.enableRetries = Setting[index].options[value].value === "On"; break; case SettingKeys.Skip_Seen_Dialogues: - scene.skipSeenDialogues = Setting[index].options[value] === "On"; + scene.skipSeenDialogues = Setting[index].options[value].value === "On"; break; case SettingKeys.Battle_Style: scene.battleStyle = value; @@ -390,7 +611,7 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): case SettingKeys.Candy_Upgrade_Display: scene.candyUpgradeDisplay = value; case SettingKeys.Money_Format: - switch (Setting[index].options[value]) { + switch (Setting[index].options[value].value) { case "Normal": scene.moneyFormat = MoneyFormat.NORMAL; break; @@ -407,22 +628,22 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): } break; case SettingKeys.Move_Animations: - scene.moveAnimations = Setting[index].options[value] === "On"; + scene.moveAnimations = Setting[index].options[value].value === "On"; break; case SettingKeys.Show_Moveset_Flyout: - scene.showMovesetFlyout = Setting[index].options[value] === "On"; + scene.showMovesetFlyout = Setting[index].options[value].value === "On"; break; case SettingKeys.Show_Arena_Flyout: - scene.showArenaFlyout = Setting[index].options[value] === "On"; + scene.showArenaFlyout = Setting[index].options[value].value === "On"; break; case SettingKeys.Show_Time_Of_Day_Widget: - scene.showTimeOfDayWidget = Setting[index].options[value] === "On"; + scene.showTimeOfDayWidget = Setting[index].options[value].value === "On"; break; case SettingKeys.Time_Of_Day_Animation: - scene.timeOfDayAnimation = Setting[index].options[value] === "Bounce" ? EaseType.BOUNCE : EaseType.BACK; + scene.timeOfDayAnimation = Setting[index].options[value].value === "Bounce" ? EaseType.BOUNCE : EaseType.BACK; break; case SettingKeys.Show_Stats_on_Level_Up: - scene.showLevelUpStats = Setting[index].options[value] === "On"; + scene.showLevelUpStats = Setting[index].options[value].value === "On"; break; case SettingKeys.EXP_Gains_Speed: scene.expGainsSpeed = value; @@ -438,7 +659,7 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): break; case SettingKeys.Player_Gender: if (scene.gameData) { - const female = Setting[index].options[value] === "Girl"; + const female = Setting[index].options[value].value === "Girl"; scene.gameData.gender = female ? PlayerGender.FEMALE : PlayerGender.MALE; scene.trainer.setTexture(scene.trainer.texture.key.replace(female ? "m" : "f", female ? "f" : "m")); } else { @@ -446,17 +667,17 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): } break; case SettingKeys.Touch_Controls: - scene.enableTouchControls = Setting[index].options[value] !== "Disabled" && hasTouchscreen(); + scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); const touchControls = document.getElementById("touchControls"); if (touchControls) { touchControls.classList.toggle("visible", scene.enableTouchControls); } break; case SettingKeys.Vibration: - scene.enableVibration = Setting[index].options[value] !== "Disabled" && hasTouchscreen(); + scene.enableVibration = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); break; case SettingKeys.Type_Hints: - scene.typeHints = Setting[index].options[value] === "On"; + scene.typeHints = Setting[index].options[value].value === "On"; break; case SettingKeys.Language: if (value) { @@ -517,7 +738,7 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): handler: () => changeLocaleHandler("ko") }, { - label: "Cancel", + label: i18next.t("settings:back"), handler: () => cancelHandler() } ], diff --git a/src/system/voucher.ts b/src/system/voucher.ts index dd0aa0ef6d4..2238a95e690 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -1,5 +1,5 @@ import BattleScene from "../battle-scene"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { Achv, AchvTier, achvs, getAchievementDescription } from "./achv"; import { PlayerGender } from "#enums/player-gender"; import { TrainerType } from "#enums/trainer-type"; diff --git a/src/test/abilities/battery.test.ts b/src/test/abilities/battery.test.ts new file mode 100644 index 00000000000..93bac836f61 --- /dev/null +++ b/src/test/abilities/battery.test.ts @@ -0,0 +1,125 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { Species } from "#enums/species"; +import { TurnEndPhase, } from "#app/phases"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import Move, { allMoves, MoveCategory } from "#app/data/move.js"; +import { AllyMoveCategoryPowerBoostAbAttr } from "#app/data/ability.js"; +import { NumberHolder } from "#app/utils.js"; +import Pokemon from "#app/field/pokemon.js"; + +describe("Abilities - Battery", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.ROCK_SLIDE, Moves.SPLASH, Moves.HEAT_WAVE]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + }); + + it("raises the power of allies' special moves by 30%", async () => { + const moveToBeUsed = Moves.HEAT_WAVE; + const basePower = allMoves[moveToBeUsed].power; + + await game.startBattle([Species.MAGIKARP, Species.CHARJABUG]); + + game.doAttack(getMovePosition(game.scene, 0, moveToBeUsed)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); + + const multiplier = getAttrPowerMultiplier(game.scene.getPlayerField()[1]); + const appliedPower = getAppliedMovePower(game.scene.getEnemyField()[0], game.scene.getPlayerField()[0], allMoves[moveToBeUsed]); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(appliedPower).not.toBe(undefined); + expect(appliedPower).not.toBe(basePower); + expect(appliedPower).toBe(basePower * multiplier); + }); + + it("does not raise the power of allies' non-special moves", async () => { + const moveToBeUsed = Moves.ROCK_SLIDE; + const basePower = allMoves[moveToBeUsed].power; + + await game.startBattle([Species.MAGIKARP, Species.CHARJABUG]); + + game.doAttack(getMovePosition(game.scene, 0, moveToBeUsed)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); + + const multiplier = getAttrPowerMultiplier(game.scene.getPlayerField()[1]); + const appliedPower = getAppliedMovePower(game.scene.getEnemyField()[0], game.scene.getPlayerField()[0], allMoves[moveToBeUsed]); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(appliedPower).not.toBe(undefined); + expect(appliedPower).toBe(basePower); + expect(appliedPower).not.toBe(basePower * multiplier); + }); + + it("does not raise the power of the ability owner's special moves", async () => { + const moveToBeUsed = Moves.HEAT_WAVE; + const basePower = allMoves[moveToBeUsed].power; + + await game.startBattle([Species.CHARJABUG, Species.MAGIKARP]); + + game.doAttack(getMovePosition(game.scene, 0, moveToBeUsed)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); + + const multiplier = getAttrPowerMultiplier(game.scene.getPlayerField()[0]); + const appliedPower = getAppliedMovePower(game.scene.getEnemyField()[0], game.scene.getPlayerField()[0], allMoves[moveToBeUsed]); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(appliedPower).not.toBe(undefined); + expect(appliedPower).toBe(basePower); + expect(appliedPower).not.toBe(basePower * multiplier); + }); +}); + +/** + * Calculates the adjusted applied power of a move. + * + * @param defender - The defending Pokémon. + * @param attacker - The attacking Pokémon. + * @param move - The move being used by the attacker. + * @returns The adjusted power of the move. + */ +const getAppliedMovePower = (defender: Pokemon, attacker: Pokemon, move: Move) => { + const powerHolder = new NumberHolder(move.power); + + /** + * @see AllyMoveCategoryPowerBoostAbAttr + */ + if (attacker.getAlly().hasAbilityWithAttr(AllyMoveCategoryPowerBoostAbAttr)) { + const batteryInstance = new AllyMoveCategoryPowerBoostAbAttr([MoveCategory.SPECIAL], 1.3); + batteryInstance.applyPreAttack(attacker, false, defender, move, [ powerHolder ]); + } + + return powerHolder.value; +}; + +/** + * Retrieves the power multiplier from a Pokémon's ability attribute. + * + * @param pokemon - The Pokémon whose ability attributes are being queried. + * @returns The power multiplier of the `AllyMoveCategoryPowerBoostAbAttr` attribute. + */ +const getAttrPowerMultiplier = (pokemon: Pokemon) => { + const attr = pokemon.getAbilityAttrs(AllyMoveCategoryPowerBoostAbAttr); + + return (attr[0] as AllyMoveCategoryPowerBoostAbAttr)["powerMultiplier"]; +}; diff --git a/src/test/abilities/power_spot.test.ts b/src/test/abilities/power_spot.test.ts new file mode 100644 index 00000000000..5450aee9742 --- /dev/null +++ b/src/test/abilities/power_spot.test.ts @@ -0,0 +1,125 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { Species } from "#enums/species"; +import { TurnEndPhase, } from "#app/phases"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import Move, { allMoves, MoveCategory } from "#app/data/move.js"; +import { AllyMoveCategoryPowerBoostAbAttr } from "#app/data/ability.js"; +import { NumberHolder } from "#app/utils.js"; +import Pokemon from "#app/field/pokemon.js"; + +describe("Abilities - Power Spot", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.ROCK_SLIDE, Moves.SPLASH, Moves.HEAT_WAVE]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + }); + + it("raises the power of allies' special moves by 30%", async () => { + const moveToBeUsed = Moves.HEAT_WAVE; + const basePower = allMoves[moveToBeUsed].power; + + await game.startBattle([Species.MAGIKARP, Species.STONJOURNER]); + + game.doAttack(getMovePosition(game.scene, 0, moveToBeUsed)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); + + const multiplier = getAttrPowerMultiplier(game.scene.getPlayerField()[1]); + const appliedPower = getAppliedMovePower(game.scene.getEnemyField()[0], game.scene.getPlayerField()[0], allMoves[moveToBeUsed]); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(appliedPower).not.toBe(undefined); + expect(appliedPower).not.toBe(basePower); + expect(appliedPower).toBe(basePower * multiplier); + }); + + it("raises the power of allies' physical moves by 30%", async () => { + const moveToBeUsed = Moves.ROCK_SLIDE; + const basePower = allMoves[moveToBeUsed].power; + + await game.startBattle([Species.MAGIKARP, Species.STONJOURNER]); + + game.doAttack(getMovePosition(game.scene, 0, moveToBeUsed)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); + + const multiplier = getAttrPowerMultiplier(game.scene.getPlayerField()[1]); + const appliedPower = getAppliedMovePower(game.scene.getEnemyField()[0], game.scene.getPlayerField()[0], allMoves[moveToBeUsed]); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(appliedPower).not.toBe(undefined); + expect(appliedPower).not.toBe(basePower); + expect(appliedPower).toBe(basePower * multiplier); + }); + + it("does not raise the power of the ability owner's moves", async () => { + const moveToBeUsed = Moves.HEAT_WAVE; + const basePower = allMoves[moveToBeUsed].power; + + await game.startBattle([Species.STONJOURNER, Species.MAGIKARP]); + + game.doAttack(getMovePosition(game.scene, 0, moveToBeUsed)); + game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH)); + + const multiplier = getAttrPowerMultiplier(game.scene.getPlayerField()[0]); + const appliedPower = getAppliedMovePower(game.scene.getEnemyField()[0], game.scene.getPlayerField()[0], allMoves[moveToBeUsed]); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(appliedPower).not.toBe(undefined); + expect(appliedPower).toBe(basePower); + expect(appliedPower).not.toBe(basePower * multiplier); + }); +}); + +/** + * Calculates the adjusted applied power of a move. + * + * @param defender - The defending Pokémon. + * @param attacker - The attacking Pokémon. + * @param move - The move being used by the attacker. + * @returns The adjusted power of the move. + */ +const getAppliedMovePower = (defender: Pokemon, attacker: Pokemon, move: Move) => { + const powerHolder = new NumberHolder(move.power); + + /** + * @see AllyMoveCategoryPowerBoostAbAttr + */ + if (attacker.getAlly().hasAbilityWithAttr(AllyMoveCategoryPowerBoostAbAttr)) { + const powerSpotInstance = new AllyMoveCategoryPowerBoostAbAttr([MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3); + powerSpotInstance.applyPreAttack(attacker, false, defender, move, [ powerHolder ]); + } + + return powerHolder.value; +}; + +/** + * Retrieves the power multiplier from a Pokémon's ability attribute. + * + * @param pokemon - The Pokémon whose ability attributes are being queried. + * @returns The power multiplier of the `AllyMoveCategoryPowerBoostAbAttr` attribute. + */ +const getAttrPowerMultiplier = (pokemon: Pokemon) => { + const attr = pokemon.getAbilityAttrs(AllyMoveCategoryPowerBoostAbAttr); + + return (attr[0] as AllyMoveCategoryPowerBoostAbAttr)["powerMultiplier"]; +}; diff --git a/src/test/abilities/screen_cleaner.test.ts b/src/test/abilities/screen_cleaner.test.ts new file mode 100644 index 00000000000..1c9943fbfc8 --- /dev/null +++ b/src/test/abilities/screen_cleaner.test.ts @@ -0,0 +1,83 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { Species } from "#enums/species"; +import { PostSummonPhase, TurnEndPhase, } from "#app/phases"; +import { Moves } from "#enums/moves"; +import { getMovePosition } from "#app/test/utils/gameManagerUtils"; +import { Abilities } from "#enums/abilities"; +import { ArenaTagType } from "#app/enums/arena-tag-type.js"; + +describe("Abilities - Screen Cleaner", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SCREEN_CLEANER); + }); + + it("removes Aurora Veil", async () => { + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HAIL]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); + + await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); + + game.doAttack(getMovePosition(game.scene, 0, Moves.HAIL)); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.arena.getTag(ArenaTagType.AURORA_VEIL)).toBeDefined(); + + await game.toNextTurn(); + game.doSwitchPokemon(1); + await game.phaseInterceptor.to(PostSummonPhase); + + expect(game.scene.arena.getTag(ArenaTagType.AURORA_VEIL)).toBeUndefined(); + }); + + it("removes Light Screen", async () => { + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); + + await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.arena.getTag(ArenaTagType.LIGHT_SCREEN)).toBeDefined(); + + await game.toNextTurn(); + game.doSwitchPokemon(1); + await game.phaseInterceptor.to(PostSummonPhase); + + expect(game.scene.arena.getTag(ArenaTagType.LIGHT_SCREEN)).toBeUndefined(); + }); + + it("removes Reflect", async () => { + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); + + await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH)); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.arena.getTag(ArenaTagType.REFLECT)).toBeDefined(); + + await game.toNextTurn(); + game.doSwitchPokemon(1); + await game.phaseInterceptor.to(PostSummonPhase); + + expect(game.scene.arena.getTag(ArenaTagType.REFLECT)).toBeUndefined(); + }); +}); diff --git a/src/test/abilities/serene_grace.test.ts b/src/test/abilities/serene_grace.test.ts new file mode 100644 index 00000000000..cf283ea92a8 --- /dev/null +++ b/src/test/abilities/serene_grace.test.ts @@ -0,0 +1,110 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#enums/abilities"; +import {applyAbAttrs ,MoveEffectChanceMultiplierAbAttr} from "#app/data/ability"; +import {Species} from "#enums/species"; +import { + CommandPhase, + MoveEffectPhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Stat} from "#app/data/pokemon-stat"; +import {Moves} from "#enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import * as Utils from "#app/utils"; + + +describe("Abilities - Serene Grace", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const movesToUse = [Moves.AIR_SLASH, Moves.TACKLE]; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + it("Move chance without Serene Grace", async() => { + const moveToUse = Moves.AIR_SLASH; + await game.startBattle([ + Species.PIDGEOT + ]); + + + game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; + game.scene.getEnemyParty()[0].stats[Stat.SPD] = 1; + expect(game.scene.getParty()[0].formIndex).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + // Check chance of Air Slash without Serene Grace + const phase = game.scene.getCurrentPhase() as MoveEffectPhase; + const move = phase.move.getMove(); + expect(move.id).toBe(Moves.AIR_SLASH); + + const chance = new Utils.IntegerHolder(move.chance); + console.log(move.chance + " Their ability is " + phase.getUserPokemon().getAbility().name); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon(), null, chance, move, phase.getTarget(), false); + expect(chance.value).toBe(30); + + }, 20000); + + it("Move chance with Serene Grace", async() => { + const moveToUse = Moves.AIR_SLASH; + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SERENE_GRACE); + await game.startBattle([ + Species.TOGEKISS + ]); + + game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; + game.scene.getEnemyParty()[0].stats[Stat.SPD] = 1; + expect(game.scene.getParty()[0].formIndex).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + // Check chance of Air Slash with Serene Grace + const phase = game.scene.getCurrentPhase() as MoveEffectPhase; + const move = phase.move.getMove(); + expect(move.id).toBe(Moves.AIR_SLASH); + + const chance = new Utils.IntegerHolder(move.chance); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon(), null, chance, move, phase.getTarget(), false); + expect(chance.value).toBe(60); + + }, 20000); + + //TODO King's Rock Interaction Unit Test +}); diff --git a/src/test/abilities/sheer_force.test.ts b/src/test/abilities/sheer_force.test.ts new file mode 100644 index 00000000000..c01ec176f4d --- /dev/null +++ b/src/test/abilities/sheer_force.test.ts @@ -0,0 +1,208 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Abilities} from "#enums/abilities"; +import {applyAbAttrs ,applyPreAttackAbAttrs,applyPostDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, MovePowerBoostAbAttr, PostDefendTypeChangeAbAttr} from "#app/data/ability"; +import {Species} from "#enums/species"; +import { + CommandPhase, + MoveEffectPhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Stat} from "#app/data/pokemon-stat"; +import {Moves} from "#enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import * as Utils from "#app/utils"; + + +describe("Abilities - Sheer Force", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const movesToUse = [Moves.AIR_SLASH, Moves.BIND, Moves.CRUSH_CLAW, Moves.TACKLE]; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + it("Sheer Force", async() => { + const moveToUse = Moves.AIR_SLASH; + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + await game.startBattle([ + Species.PIDGEOT + ]); + + + game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; + game.scene.getEnemyParty()[0].stats[Stat.SPD] = 1; + expect(game.scene.getParty()[0].formIndex).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + const phase = game.scene.getCurrentPhase() as MoveEffectPhase; + const move = phase.move.getMove(); + expect(move.id).toBe(Moves.AIR_SLASH); + + //Verify the move is boosted and has no chance of secondary effects + const power = new Utils.IntegerHolder(move.power); + const chance = new Utils.IntegerHolder(move.chance); + + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon(), null, chance, move, phase.getTarget(), false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon(), phase.getTarget(), move, power); + + expect(chance.value).toBe(0); + expect(power.value).toBe(move.power * 5461/4096); + + + }, 20000); + + it("Sheer Force with exceptions including binding moves", async() => { + const moveToUse = Moves.BIND; + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + await game.startBattle([ + Species.PIDGEOT + ]); + + + game.scene.getEnemyParty()[0].stats[Stat.DEF] = 10000; + game.scene.getEnemyParty()[0].stats[Stat.SPD] = 1; + expect(game.scene.getParty()[0].formIndex).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + const phase = game.scene.getCurrentPhase() as MoveEffectPhase; + const move = phase.move.getMove(); + expect(move.id).toBe(Moves.BIND); + + //Binding moves and other exceptions are not affected by Sheer Force and have a chance.value of -1 + const power = new Utils.IntegerHolder(move.power); + const chance = new Utils.IntegerHolder(move.chance); + + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon(), null, chance, move, phase.getTarget(), false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon(), phase.getTarget(), move, power); + + expect(chance.value).toBe(-1); + expect(power.value).toBe(move.power); + + + }, 20000); + + it("Sheer Force with moves with no secondary effect", async() => { + const moveToUse = Moves.TACKLE; + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + await game.startBattle([ + Species.PIDGEOT + ]); + + + game.scene.getEnemyParty()[0].stats[Stat.DEF] = 10000; + game.scene.getEnemyParty()[0].stats[Stat.SPD] = 1; + expect(game.scene.getParty()[0].formIndex).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + const phase = game.scene.getCurrentPhase() as MoveEffectPhase; + const move = phase.move.getMove(); + expect(move.id).toBe(Moves.TACKLE); + + //Binding moves and other exceptions are not affected by Sheer Force and have a chance.value of -1 + const power = new Utils.IntegerHolder(move.power); + const chance = new Utils.IntegerHolder(move.chance); + + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon(), null, chance, move, phase.getTarget(), false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, phase.getUserPokemon(), phase.getTarget(), move, power); + + expect(chance.value).toBe(-1); + expect(power.value).toBe(move.power); + + + }, 20000); + + it("Sheer Force Disabling Specific Abilities", async() => { + const moveToUse = Moves.CRUSH_CLAW; + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.COLOR_CHANGE); + vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "KINGS_ROCK", count: 1}]); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHEER_FORCE); + await game.startBattle([ + Species.PIDGEOT + ]); + + + game.scene.getEnemyParty()[0].stats[Stat.DEF] = 10000; + game.scene.getEnemyParty()[0].stats[Stat.SPD] = 1; + expect(game.scene.getParty()[0].formIndex).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + const phase = game.scene.getCurrentPhase() as MoveEffectPhase; + const move = phase.move.getMove(); + expect(move.id).toBe(Moves.CRUSH_CLAW); + + //Disable color change due to being hit by Sheer Force + const power = new Utils.IntegerHolder(move.power); + const chance = new Utils.IntegerHolder(move.chance); + const user = phase.getUserPokemon(); + const target = phase.getTarget(); + const opponentType = target.getTypes()[0]; + + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, chance, move, target, false); + applyPreAttackAbAttrs(MovePowerBoostAbAttr, user, target, move, power); + applyPostDefendAbAttrs(PostDefendTypeChangeAbAttr, target, user, move, target.apply(user, move)); + + expect(chance.value).toBe(0); + expect(power.value).toBe(move.power * 5461/4096); + expect(target.getTypes().length).toBe(2); + expect(target.getTypes()[0]).toBe(opponentType); + + }, 20000); + + //TODO King's Rock Interaction Unit Test +}); diff --git a/src/test/abilities/shield_dust.test.ts b/src/test/abilities/shield_dust.test.ts new file mode 100644 index 00000000000..f52a1d6c7d4 --- /dev/null +++ b/src/test/abilities/shield_dust.test.ts @@ -0,0 +1,79 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { Abilities } from "#enums/abilities"; +import {applyAbAttrs ,applyPreDefendAbAttrs,IgnoreMoveEffectsAbAttr,MoveEffectChanceMultiplierAbAttr} from "#app/data/ability"; +import {Species} from "#enums/species"; +import { + CommandPhase, + MoveEffectPhase, +} from "#app/phases"; +import {Mode} from "#app/ui/ui"; +import {Stat} from "#app/data/pokemon-stat"; +import {Moves} from "#enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import {Command} from "#app/ui/command-ui-handler"; +import * as Utils from "#app/utils"; + + +describe("Abilities - Shield Dust", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const movesToUse = [Moves.AIR_SLASH]; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ONIX); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHIELD_DUST); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(movesToUse); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + it("Shield Dust", async() => { + const moveToUse = Moves.AIR_SLASH; + await game.startBattle([ + Species.PIDGEOT + ]); + + + game.scene.getEnemyParty()[0].stats[Stat.SPDEF] = 10000; + game.scene.getEnemyParty()[0].stats[Stat.SPD] = 1; + expect(game.scene.getParty()[0].formIndex).toBe(0); + + game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { + game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + }); + game.onNextPrompt("CommandPhase", Mode.FIGHT, () => { + const movePosition = getMovePosition(game.scene, 0, moveToUse); + (game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); + }); + + await game.phaseInterceptor.to(MoveEffectPhase, false); + + // Shield Dust negates secondary effect + const phase = game.scene.getCurrentPhase() as MoveEffectPhase; + const move = phase.move.getMove(); + expect(move.id).toBe(Moves.AIR_SLASH); + + const chance = new Utils.IntegerHolder(move.chance); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, phase.getUserPokemon(), null, chance, move, phase.getTarget(), false); + applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, phase.getTarget(),phase.getUserPokemon(),null,null, chance); + expect(chance.value).toBe(0); + + }, 20000); + + //TODO King's Rock Interaction Unit Test +}); diff --git a/src/test/abilities/sturdy.test.ts b/src/test/abilities/sturdy.test.ts new file mode 100644 index 00000000000..7bfac5e8f18 --- /dev/null +++ b/src/test/abilities/sturdy.test.ts @@ -0,0 +1,95 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { + TurnEndPhase, +} from "#app/phases"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { EnemyPokemon } from "#app/field/pokemon.js"; + +const TIMEOUT = 20 * 1000; + +describe("Abilities - Sturdy", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.LUCARIO); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.CLOSE_COMBAT, Moves.FISSURE]); + + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ARON); + vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(5); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.STURDY); + }); + + test( + "Sturdy activates when user is at full HP", + async () => { + await game.startBattle(); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLOSE_COMBAT)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(game.scene.getEnemyParty()[0].hp).toBe(1); + }, + TIMEOUT + ); + + test( + "Sturdy doesn't activate when user is not at full HP", + async () => { + await game.startBattle(); + const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; + enemyPokemon.hp = enemyPokemon.getMaxHp() - 1; + game.doAttack(getMovePosition(game.scene, 0, Moves.CLOSE_COMBAT)); + await game.phaseInterceptor.to(TurnEndPhase); + expect(enemyPokemon.hp).toBe(0); + expect(enemyPokemon.isFainted()).toBe(true); + }, + TIMEOUT + ); + + test( + "Sturdy pokemon should be inmune to OHKO moves", + async () => { + await game.startBattle(); + game.doAttack(getMovePosition(game.scene, 0, Moves.FISSURE)); + await game.phaseInterceptor.to(TurnEndPhase); + const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; + expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + }, + TIMEOUT + ); + + test( + "Sturdy is ignored by pokemon with `Abilities.MOLD_BREAKER`", + async () => { + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.MOLD_BREAKER); + + await game.startBattle(); + game.doAttack(getMovePosition(game.scene, 0, Moves.CLOSE_COMBAT)); + await game.phaseInterceptor.to(TurnEndPhase); + const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; + expect(enemyPokemon.hp).toBe(0); + expect(enemyPokemon.isFainted()).toBe(true); + }, + TIMEOUT + ); + +}); diff --git a/src/test/lokalisation/battle-stat.test.ts b/src/test/lokalisation/battle-stat.test.ts index 99269c6ec4c..cd21f638258 100644 --- a/src/test/lokalisation/battle-stat.test.ts +++ b/src/test/lokalisation/battle-stat.test.ts @@ -21,6 +21,7 @@ import { pokemonInfo as zhTwPokemonInfo } from "#app/locales/zh_TW/pokemon-info. import { battle as zhTwBattleStat } from "#app/locales/zh_TW/battle.js"; import i18next, {initI18n} from "#app/plugins/i18n"; +import { KoreanPostpositionProcessor } from "i18next-korean-postposition-processor"; interface BattleStatTestUnit { stat: BattleStat, @@ -198,7 +199,9 @@ describe("Test for BattleStat Localization", () => { it("Test getBattleStatLevelChangeDescription() in 한국어", async () => { i18next.changeLanguage("ko", () => { battleStatLevelUnits.forEach(unit => { - testBattleStatLevelChangeDescription(unit.levels, unit.up, koBattleStat[unit.key]); + const processor = new KoreanPostpositionProcessor(); + const message = processor.process(koBattleStat[unit.key]); + testBattleStatLevelChangeDescription(unit.levels, unit.up, message); }); }); }); diff --git a/src/test/moves/follow_me.test.ts b/src/test/moves/follow_me.test.ts new file mode 100644 index 00000000000..54b972e7cc0 --- /dev/null +++ b/src/test/moves/follow_me.test.ts @@ -0,0 +1,166 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { + CommandPhase, + SelectTargetPhase, + TurnEndPhase, +} from "#app/phases"; +import {Stat} from "#app/data/pokemon-stat"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { BattlerIndex } from "#app/battle.js"; +import { Abilities } from "#app/enums/abilities.js"; + +const TIMEOUT = 20 * 1000; + +describe("Moves - Follow Me", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + test( + "move should redirect enemy attacks to the user", + async () => { + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + playerPokemon.forEach(p => p.hp = 200); + + game.doAttack(getMovePosition(game.scene, 0, Moves.FOLLOW_ME)); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(playerPokemon[0].hp).toBeLessThan(200); + expect(playerPokemon[1].hp).toBe(200); + }, TIMEOUT + ); + + test( + "move should redirect enemy attacks to the first ally that uses it", + async () => { + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + playerPokemon.forEach(p => p.hp = 200); + + game.doAttack(getMovePosition(game.scene, 0, Moves.FOLLOW_ME)); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.FOLLOW_ME)); + await game.phaseInterceptor.to(TurnEndPhase); + + playerPokemon.sort((a, b) => a.getBattleStat(Stat.SPD) - b.getBattleStat(Stat.SPD)); + + expect(playerPokemon[1].hp).toBeLessThan(200); + expect(playerPokemon[0].hp).toBe(200); + }, TIMEOUT + ); + + test( + "move effect should be bypassed by Stalwart", + async () => { + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.STALWART); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.QUICK_ATTACK ]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); + + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + enemyPokemon.forEach(p => p.hp = 200); + + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); + await game.phaseInterceptor.to(TurnEndPhase); + + // If redirection was bypassed, both enemies should be damaged + enemyPokemon.forEach(p => expect(p.hp).toBeLessThan(200)); + }, TIMEOUT + ); + + test( + "move effect should be bypassed by Snipe Shot", + async () => { + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.SNIPE_SHOT ]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); + + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + enemyPokemon.forEach(p => p.hp = 200); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SNIPE_SHOT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.SNIPE_SHOT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); + await game.phaseInterceptor.to(TurnEndPhase); + + // If redirection was bypassed, both enemies should be damaged + enemyPokemon.forEach(p => expect(p.hp).toBeLessThan(200)); + }, TIMEOUT + ); +}); diff --git a/src/test/moves/magnet_rise.test.ts b/src/test/moves/magnet_rise.test.ts new file mode 100644 index 00000000000..7ed5b84654c --- /dev/null +++ b/src/test/moves/magnet_rise.test.ts @@ -0,0 +1,61 @@ +import {beforeAll, afterEach, beforeEach, describe, vi, it, expect} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Moves} from "#enums/moves"; +import {Species} from "#enums/species"; +import {CommandPhase, TurnEndPhase} from "#app/phases.js"; + +describe("Moves - Magnet Rise", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + const moveToUse = Moves.MAGNET_RISE; + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGNEZONE); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN]); + vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(1); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse, Moves.SPLASH, Moves.GRAVITY, Moves.BATON_PASS]); + }); + + it("MAGNET RISE", async () => { + await game.startBattle(); + + const startingHp = game.scene.getParty()[0].hp; + game.doAttack(0); + await game.phaseInterceptor.to(TurnEndPhase); + const finalHp = game.scene.getParty()[0].hp; + const hpLost = finalHp - startingHp; + expect(hpLost).toBe(0); + }, 20000); + + it("MAGNET RISE - Gravity", async () => { + await game.startBattle(); + + const startingHp = game.scene.getParty()[0].hp; + game.doAttack(0); + await game.phaseInterceptor.to(CommandPhase); + let finalHp = game.scene.getParty()[0].hp; + let hpLost = finalHp - startingHp; + expect(hpLost).toBe(0); + game.doAttack(2); + await game.phaseInterceptor.to(TurnEndPhase); + finalHp = game.scene.getParty()[0].hp; + hpLost = finalHp - startingHp; + expect(hpLost).not.toBe(0); + }, 20000); +}); diff --git a/src/test/moves/rage_powder.test.ts b/src/test/moves/rage_powder.test.ts new file mode 100644 index 00000000000..6a204877150 --- /dev/null +++ b/src/test/moves/rage_powder.test.ts @@ -0,0 +1,107 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { + CommandPhase, + SelectTargetPhase, + TurnEndPhase, +} from "#app/phases"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { BattlerIndex } from "#app/battle.js"; + +const TIMEOUT = 20 * 1000; + +describe("Moves - Rage Powder", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + test( + "move effect should be bypassed by Grass type", + async () => { + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); + + await game.startBattle([ Species.AMOONGUSS, Species.VENUSAUR ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + enemyPokemon.forEach(p => p.hp = 200); + + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); + await game.phaseInterceptor.to(TurnEndPhase); + + // If redirection was bypassed, both enemies should be damaged + enemyPokemon.forEach(p => expect(p.hp).toBeLessThan(200)); + }, TIMEOUT + ); + + test( + "move effect should be bypassed by Overcoat", + async () => { + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.OVERCOAT); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER, Moves.RAGE_POWDER ]); + + // Test with two non-Grass type player Pokemon + await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + enemyPokemon.forEach(p => p.hp = 200); + + game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); + await game.phaseInterceptor.to(TurnEndPhase); + + // If redirection was bypassed, both enemies should be damaged + enemyPokemon.forEach(p => expect(p.hp).toBeLessThan(200)); + }, TIMEOUT + ); +}); diff --git a/src/test/moves/spotlight.test.ts b/src/test/moves/spotlight.test.ts new file mode 100644 index 00000000000..188207b713c --- /dev/null +++ b/src/test/moves/spotlight.test.ts @@ -0,0 +1,111 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, test, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import { + CommandPhase, + SelectTargetPhase, + TurnEndPhase, +} from "#app/phases"; +import {Stat} from "#app/data/pokemon-stat"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { BattlerIndex } from "#app/battle.js"; + +const TIMEOUT = 20 * 1000; + +describe("Moves - Spotlight", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.AMOONGUSS); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX); + vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100); + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]); + }); + + test( + "move should redirect attacks to the target", + async () => { + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + enemyPokemon.forEach(p => p.hp = 200); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SPOTLIGHT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(BattlerIndex.ENEMY_2); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(enemyPokemon[0].hp).toBeLessThan(200); + expect(enemyPokemon[1].hp).toBe(200); + }, TIMEOUT + ); + + test( + "move should cause other redirection moves to fail", + async () => { + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([ Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME, Moves.FOLLOW_ME ]); + + await game.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerField(); + expect(playerPokemon.length).toBe(2); + playerPokemon.forEach(p => expect(p).not.toBe(undefined)); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon.length).toBe(2); + enemyPokemon.forEach(p => expect(p).not.toBe(undefined)); + + enemyPokemon.forEach(p => p.hp = 200); + + /** + * Spotlight will target the slower enemy. In this situation without Spotlight being used, + * the faster enemy would normally end up with the Center of Attention tag. + */ + enemyPokemon.sort((a, b) => b.getBattleStat(Stat.SPD) - a.getBattleStat(Stat.SPD)); + const spotTarget = enemyPokemon[1].getBattlerIndex(); + const attackTarget = enemyPokemon[0].getBattlerIndex(); + + game.doAttack(getMovePosition(game.scene, 0, Moves.SPOTLIGHT)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(spotTarget); + await game.phaseInterceptor.to(CommandPhase); + + game.doAttack(getMovePosition(game.scene, 1, Moves.QUICK_ATTACK)); + await game.phaseInterceptor.to(SelectTargetPhase, false); + game.doSelectTarget(attackTarget); + await game.phaseInterceptor.to(TurnEndPhase); + + expect(enemyPokemon[1].hp).toBeLessThan(200); + expect(enemyPokemon[0].hp).toBe(200); + }, TIMEOUT + ); +}); diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index e0585395ff9..84d39024dc9 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -5,9 +5,11 @@ import { CommandPhase, EncounterPhase, FaintPhase, - LoginPhase, NewBattlePhase, + LoginPhase, + NewBattlePhase, SelectStarterPhase, TitlePhase, TurnInitPhase, + TurnStartPhase, } from "#app/phases"; import BattleScene from "#app/battle-scene.js"; import PhaseInterceptor from "#app/test/utils/phaseInterceptor"; @@ -29,6 +31,8 @@ import { GameDataType } from "#enums/game-data-type"; import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; import { Button } from "#enums/buttons"; +import { BattlerIndex } from "#app/battle.js"; +import TargetSelectUiHandler from "#app/ui/target-select-ui-handler.js"; /** * Class to manage the game state and transitions between phases. @@ -168,6 +172,19 @@ export default class GameManager { }); } + /** + * Emulate a player's target selection after an attack is chosen, + * usually called after {@linkcode doAttack} in a double battle. + * @param {BattlerIndex} targetIndex the index of the attack target + */ + doSelectTarget(targetIndex: BattlerIndex) { + this.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = this.scene.ui.getHandler() as TargetSelectUiHandler; + handler.setCursor(targetIndex); + handler.processInput(Button.ACTION); + }, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(TurnStartPhase)); + } + /** Faint all opponents currently on the field */ async doKillOpponents() { await this.killPokemon(this.scene.currentBattle.enemyParty[0]); diff --git a/src/tutorial.ts b/src/tutorial.ts index ecb45e543a1..c4482839779 100644 --- a/src/tutorial.ts +++ b/src/tutorial.ts @@ -1,7 +1,7 @@ import BattleScene from "./battle-scene"; import AwaitableUiHandler from "./ui/awaitable-ui-handler"; import { Mode } from "./ui/ui"; -import i18next from "./plugins/i18n"; +import i18next from "i18next"; export enum Tutorial { Intro = "INTRO", diff --git a/src/ui-inputs.ts b/src/ui-inputs.ts index 00c88504ef1..9288fd35892 100644 --- a/src/ui-inputs.ts +++ b/src/ui-inputs.ts @@ -190,12 +190,12 @@ export class UiInputs { buttonSpeedChange(up = true): void { const settingGameSpeed = settingIndex(SettingKeys.Game_Speed); if (up && this.scene.gameSpeed < 5) { - this.scene.gameData.saveSetting(SettingKeys.Game_Speed, Setting[settingGameSpeed].options.indexOf(`${this.scene.gameSpeed}x`) + 1); + this.scene.gameData.saveSetting(SettingKeys.Game_Speed, Setting[settingGameSpeed].options.findIndex((item) => item.label === `${this.scene.gameSpeed}x`) + 1); if (this.scene.ui?.getMode() === Mode.SETTINGS) { (this.scene.ui.getHandler() as SettingsUiHandler).show([]); } } else if (!up && this.scene.gameSpeed > 1) { - this.scene.gameData.saveSetting(SettingKeys.Game_Speed, Math.max(Setting[settingGameSpeed].options.indexOf(`${this.scene.gameSpeed}x`) - 1, 0)); + this.scene.gameData.saveSetting(SettingKeys.Game_Speed, Math.max(Setting[settingGameSpeed].options.findIndex((item) => item.label === `${this.scene.gameSpeed}x`) - 1, 0)); if (this.scene.ui?.getMode() === Mode.SETTINGS) { (this.scene.ui.getHandler() as SettingsUiHandler).show([]); } diff --git a/src/ui/achvs-ui-handler.ts b/src/ui/achvs-ui-handler.ts index 843ebc4e266..b5e17ce2b67 100644 --- a/src/ui/achvs-ui-handler.ts +++ b/src/ui/achvs-ui-handler.ts @@ -1,6 +1,6 @@ import BattleScene from "../battle-scene"; import { Button } from "#enums/buttons"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { Achv, achvs, getAchievementDescription } from "../system/achv"; import MessageUiHandler from "./message-ui-handler"; import { addTextObject, TextStyle } from "./text"; diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index 6edb359746a..49482d5c575 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -7,7 +7,7 @@ import { getStatName, Stat } from "../data/pokemon-stat"; import { addWindow } from "./ui-theme"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import {Button} from "#enums/buttons"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; export default class BattleMessageUiHandler extends MessageUiHandler { private levelUpStatsContainer: Phaser.GameObjects.Container; diff --git a/src/ui/challenges-select-ui-handler.ts b/src/ui/challenges-select-ui-handler.ts index ae613c69a4d..1104b048f93 100644 --- a/src/ui/challenges-select-ui-handler.ts +++ b/src/ui/challenges-select-ui-handler.ts @@ -4,7 +4,7 @@ import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; import {Button} from "#enums/buttons"; -import i18next from "#app/plugins/i18n.js"; +import i18next from "i18next"; import { SelectStarterPhase, TitlePhase } from "#app/phases.js"; import { Challenge } from "#app/data/challenge.js"; diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index 67b587fd076..852b1f855b6 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -4,7 +4,7 @@ import { addTextObject, TextStyle } from "./text"; import PartyUiHandler, { PartyUiMode } from "./party-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import {Button} from "#enums/buttons"; export enum Command { diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index aa0cce62525..212d7b2a66c 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -1,8 +1,8 @@ +import i18next from "i18next"; import BattleScene from "../battle-scene"; +import * as Utils from "../utils"; import { TextStyle, addTextObject } from "./text"; import { WindowVariant, addWindow } from "./ui-theme"; -import * as Utils from "../utils"; -import i18next from "i18next"; interface RankingEntry { rank: integer, @@ -154,7 +154,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { return entryContainer; }; - this.rankingsContainer.add(getEntry("#", "Username", "Score", "Wave")); + this.rankingsContainer.add(getEntry(i18next.t("menu:positionIcon"), i18next.t("menu:usernameScoreboard"), i18next.t("menu:score"), i18next.t("menu:wave"))); rankings.forEach((r: RankingEntry, i: integer) => { const entryContainer = getEntry(r.rank.toString(), r.username, r.score.toString(), r.wave.toString()); diff --git a/src/ui/egg-counter-container.ts b/src/ui/egg-counter-container.ts index 1c5779ef777..a688b8b7efc 100644 --- a/src/ui/egg-counter-container.ts +++ b/src/ui/egg-counter-container.ts @@ -17,7 +17,7 @@ export default class EggCounterContainer extends Phaser.GameObjects.Container { private battleScene: BattleScene; private eggCount: integer; private eggCountWindow: Phaser.GameObjects.NineSlice; - private eggCountText: Phaser.GameObjects.Text; + public eggCountText: Phaser.GameObjects.Text; /** * @param {BattleScene} scene - The scene to which this container belongs. @@ -49,6 +49,7 @@ export default class EggCounterContainer extends Phaser.GameObjects.Container { eggSprite.setScale(0.32); this.eggCountText = addTextObject(this.battleScene, 28, 13, `${this.eggCount}`, TextStyle.MESSAGE, { fontSize: "66px" }); + this.eggCountText.setName("text-egg-count"); this.add(eggSprite); this.add(this.eggCountText); @@ -69,7 +70,7 @@ export default class EggCounterContainer extends Phaser.GameObjects.Container { */ private onEggCountChanged(event: Event): void { const eggCountChangedEvent = event as EggCountChangedEvent; - if (!eggCountChangedEvent) { + if (!eggCountChangedEvent || !this.eggCountText?.data) { return; } diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 4d987ee8fcc..c17816c4c55 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -9,7 +9,7 @@ import { getPokemonSpecies } from "../data/pokemon-species"; import { addWindow } from "./ui-theme"; import { Tutorial, handleTutorial } from "../tutorial"; import {Button} from "#enums/buttons"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { EggTier } from "#enums/egg-type"; export default class EggGachaUiHandler extends MessageUiHandler { diff --git a/src/ui/egg-list-ui-handler.ts b/src/ui/egg-list-ui-handler.ts index 8c4621ffb3d..e4223824a2e 100644 --- a/src/ui/egg-list-ui-handler.ts +++ b/src/ui/egg-list-ui-handler.ts @@ -6,7 +6,7 @@ import MessageUiHandler from "./message-ui-handler"; import { Egg, getEggGachaTypeDescriptor, getEggHatchWavesMessage, getEggDescriptor } from "../data/egg"; import { addWindow } from "./ui-theme"; import {Button} from "#enums/buttons"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; export default class EggListUiHandler extends MessageUiHandler { private eggListContainer: Phaser.GameObjects.Container; diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 217f4d75820..0ee5b511b31 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -7,7 +7,7 @@ import UiHandler from "./ui-handler"; import * as Utils from "../utils"; import { CommandPhase } from "../phases"; import { MoveCategory } from "#app/data/move.js"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import {Button} from "#enums/buttons"; import Pokemon, { PokemonMove } from "#app/field/pokemon.js"; diff --git a/src/ui/form-modal-ui-handler.ts b/src/ui/form-modal-ui-handler.ts index 4c60a3bad9b..2c576a0fbaa 100644 --- a/src/ui/form-modal-ui-handler.ts +++ b/src/ui/form-modal-ui-handler.ts @@ -5,7 +5,7 @@ import { TextStyle, addTextInputObject, addTextObject } from "./text"; import { WindowVariant, addWindow } from "./ui-theme"; import InputText from "phaser3-rex-plugins/plugins/inputtext"; import * as Utils from "../utils"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import {Button} from "#enums/buttons"; export interface FormModalConfig extends ModalConfig { diff --git a/src/ui/game-stats-ui-handler.ts b/src/ui/game-stats-ui-handler.ts index 4a9c62ca012..8f1e8890a76 100644 --- a/src/ui/game-stats-ui-handler.ts +++ b/src/ui/game-stats-ui-handler.ts @@ -8,7 +8,7 @@ import * as Utils from "../utils"; import { DexAttr, GameData } from "../system/game-data"; import { speciesStarters } from "../data/pokemon-species"; import {Button} from "#enums/buttons"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; interface DisplayStat { label_key?: string; diff --git a/src/ui/login-form-ui-handler.ts b/src/ui/login-form-ui-handler.ts index 890aabeb7af..3b75c6f7c13 100644 --- a/src/ui/login-form-ui-handler.ts +++ b/src/ui/login-form-ui-handler.ts @@ -2,7 +2,7 @@ import { FormModalUiHandler } from "./form-modal-ui-handler"; import { ModalConfig } from "./modal-ui-handler"; import * as Utils from "../utils"; import { Mode } from "./ui"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; export default class LoginFormUiHandler extends FormModalUiHandler { getModalTitle(config?: ModalConfig): string { diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index b068080bdda..5b1b2caf917 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -7,7 +7,7 @@ import MessageUiHandler from "./message-ui-handler"; import { OptionSelectConfig, OptionSelectItem } from "./abstact-option-select-ui-handler"; import { Tutorial, handleTutorial } from "../tutorial"; import { updateUserInfo } from "../account"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import {Button} from "#enums/buttons"; import { GameDataType } from "#enums/game-data-type"; @@ -24,9 +24,10 @@ export enum MenuOptions { LOG_OUT } -const wikiUrl = "https://wiki.pokerogue.net"; +const wikiUrl = "https://wiki.pokerogue.net/start"; const discordUrl = "https://discord.gg/uWpTfdKG49"; const githubUrl = "https://github.com/pagefaultgames/pokerogue"; +const redditUrl = "https://www.reddit.com/r/pokerogue"; export default class MenuUiHandler extends MessageUiHandler { private menuContainer: Phaser.GameObjects.Container; @@ -211,6 +212,14 @@ export default class MenuUiHandler extends MessageUiHandler { }, keepOpen: true }, + { + label: "Reddit", + handler: () => { + window.open(redditUrl, "_blank").focus(); + return true; + }, + keepOpen: true + }, { label: i18next.t("menuUiHandler:cancel"), handler: () => { diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index f28cf2e8a48..482aeec6871 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -5,7 +5,7 @@ import { Gender, getGenderColor, getGenderSymbol } from "../data/gender"; import { getNatureName } from "../data/nature"; import { Type } from "../data/type"; import Pokemon from "../field/pokemon"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { DexAttr } from "../system/game-data"; import * as Utils from "../utils"; import ConfirmUiHandler from "./confirm-ui-handler"; diff --git a/src/ui/registration-form-ui-handler.ts b/src/ui/registration-form-ui-handler.ts index e4bb5c6395b..d5e7f239378 100644 --- a/src/ui/registration-form-ui-handler.ts +++ b/src/ui/registration-form-ui-handler.ts @@ -3,7 +3,7 @@ import { ModalConfig } from "./modal-ui-handler"; import * as Utils from "../utils"; import { Mode } from "./ui"; import { TextStyle, addTextObject } from "./text"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; export default class RegistrationFormUiHandler extends FormModalUiHandler { getModalTitle(config?: ModalConfig): string { diff --git a/src/ui/settings/abstract-binding-ui-handler.ts b/src/ui/settings/abstract-binding-ui-handler.ts index 1cc59c13035..809c4ffa2f8 100644 --- a/src/ui/settings/abstract-binding-ui-handler.ts +++ b/src/ui/settings/abstract-binding-ui-handler.ts @@ -5,6 +5,7 @@ import {addWindow} from "../ui-theme"; import {addTextObject, TextStyle} from "../text"; import {Button} from "#enums/buttons"; import {NavigationManager} from "#app/ui/settings/navigationMenu"; +import i18next from "i18next"; /** * Abstract class for handling UI elements related to button bindings. @@ -78,7 +79,7 @@ export default abstract class AbstractBindingUiHandler extends UiHandler { this.actionsContainer.add(this.actionBg); // Text prompts and instructions for the user. - this.unlockText = addTextObject(this.scene, 0, 0, "Press a button...", TextStyle.WINDOW); + this.unlockText = addTextObject(this.scene, 0, 0, i18next.t("settings:pressButton"), TextStyle.WINDOW); this.unlockText.setOrigin(0, 0); this.unlockText.setPositionRelative(this.titleBg, 36, 4); this.optionSelectContainer.add(this.unlockText); @@ -92,7 +93,7 @@ export default abstract class AbstractBindingUiHandler extends UiHandler { this.optionSelectBg.setOrigin(0.5); this.optionSelectContainer.add(this.optionSelectBg); - this.cancelLabel = addTextObject(this.scene, 0, 0, "Cancel", TextStyle.SETTINGS_LABEL); + this.cancelLabel = addTextObject(this.scene, 0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); this.cancelLabel.setOrigin(0, 0.5); this.cancelLabel.setPositionRelative(this.actionBg, 10, this.actionBg.height / 2); this.actionsContainer.add(this.cancelLabel); diff --git a/src/ui/settings/abstract-control-settings-ui-handler.ts b/src/ui/settings/abstract-control-settings-ui-handler.ts index 4abc19f9087..2ec4c437b3c 100644 --- a/src/ui/settings/abstract-control-settings-ui-handler.ts +++ b/src/ui/settings/abstract-control-settings-ui-handler.ts @@ -8,6 +8,7 @@ import {getIconWithSettingName} from "#app/configs/inputs/configHandler"; import NavigationMenu, {NavigationManager} from "#app/ui/settings/navigationMenu"; import { Device } from "#enums/devices"; import { Button } from "#enums/buttons"; +import i18next from "i18next"; export interface InputsIcons { [key: string]: Phaser.GameObjects.Sprite; @@ -83,6 +84,12 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler return settings; } + private camelize(string: string): string { + return string.replace(/(?:^\w|[A-Z]|\b\w)/g, function(word, index) { + return index === 0 ? word.toLowerCase() : word.toUpperCase(); + }).replace(/\s+/g, ""); + } + /** * Setup UI elements. */ @@ -108,7 +115,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler iconAction.setPositionRelative(this.actionsBg, this.navigationContainer.width - 32, 4); this.navigationIcons["BUTTON_ACTION"] = iconAction; - const actionText = addTextObject(this.scene, 0, 0, "Action", TextStyle.SETTINGS_LABEL); + const actionText = addTextObject(this.scene, 0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL); actionText.setOrigin(0, 0.15); actionText.setPositionRelative(iconAction, -actionText.width/6-2, 0); @@ -117,7 +124,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler iconCancel.setPositionRelative(this.actionsBg, this.navigationContainer.width - 100, 4); this.navigationIcons["BUTTON_CANCEL"] = iconCancel; - const cancelText = addTextObject(this.scene, 0, 0, "Cancel", TextStyle.SETTINGS_LABEL); + const cancelText = addTextObject(this.scene, 0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); cancelText.setOrigin(0, 0.15); cancelText.setPositionRelative(iconCancel, -cancelText.width/6-2, 0); @@ -126,7 +133,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler iconReset.setPositionRelative(this.actionsBg, this.navigationContainer.width - 180, 4); this.navigationIcons["BUTTON_HOME"] = iconReset; - const resetText = addTextObject(this.scene, 0, 0, "Reset all", TextStyle.SETTINGS_LABEL); + const resetText = addTextObject(this.scene, 0, 0, i18next.t("settings:reset"), TextStyle.SETTINGS_LABEL); resetText.setOrigin(0, 0.15); resetText.setPositionRelative(iconReset, -resetText.width/6-2, 0); @@ -178,7 +185,14 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler // Create and add a text object for the setting name to the scene. const isLock = this.settingBlacklisted.includes(this.setting[setting]); const labelStyle = isLock ? TextStyle.SETTINGS_LOCKED : TextStyle.SETTINGS_LABEL; - settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, settingName, labelStyle); + let labelText: string; + const i18nKey = this.camelize(settingName.replace("Alt ", "")); + if (settingName.toLowerCase().includes("alt")) { + labelText = `${i18next.t(`settings:${i18nKey}`)}${i18next.t("settings:alt")}`; + } else { + labelText = i18next.t(`settings:${i18nKey}`); + } + settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, labelText, labelStyle); settingLabels[s].setOrigin(0, 0); optionsContainer.add(settingLabels[s]); diff --git a/src/ui/settings/abstract-settings-ui-handler.ts b/src/ui/settings/abstract-settings-ui-handler.ts index dad797d43a5..1834d5f09dd 100644 --- a/src/ui/settings/abstract-settings-ui-handler.ts +++ b/src/ui/settings/abstract-settings-ui-handler.ts @@ -8,6 +8,7 @@ import {Button} from "#enums/buttons"; import {InputsIcons} from "#app/ui/settings/abstract-control-settings-ui-handler.js"; import NavigationMenu, {NavigationManager} from "#app/ui/settings/navigationMenu"; import { Setting, SettingKeys } from "#app/system/settings/settings"; +import i18next from "i18next"; /** @@ -71,7 +72,7 @@ export default class AbstractSettingsUiHandler extends UiHandler { iconAction.setPositionRelative(actionsBg, this.navigationContainer.width - 32, 4); this.navigationIcons["BUTTON_ACTION"] = iconAction; - const actionText = addTextObject(this.scene, 0, 0, "Action", TextStyle.SETTINGS_LABEL); + const actionText = addTextObject(this.scene, 0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL); actionText.setOrigin(0, 0.15); actionText.setPositionRelative(iconAction, -actionText.width/6-2, 0); @@ -80,7 +81,7 @@ export default class AbstractSettingsUiHandler extends UiHandler { iconCancel.setPositionRelative(actionsBg, this.navigationContainer.width - 100, 4); this.navigationIcons["BUTTON_CANCEL"] = iconCancel; - const cancelText = addTextObject(this.scene, 0, 0, "Cancel", TextStyle.SETTINGS_LABEL); + const cancelText = addTextObject(this.scene, 0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); cancelText.setOrigin(0, 0.15); cancelText.setPositionRelative(iconCancel, -cancelText.width/6-2, 0); @@ -95,7 +96,7 @@ export default class AbstractSettingsUiHandler extends UiHandler { .forEach((setting, s) => { let settingName = setting.label; if (setting?.requireReload) { - settingName += " (Requires Reload)"; + settingName += ` (${i18next.t("settings:requireReload")})`; } this.settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL); @@ -103,7 +104,7 @@ export default class AbstractSettingsUiHandler extends UiHandler { this.optionsContainer.add(this.settingLabels[s]); this.optionValueLabels.push(setting.options.map((option, o) => { - const valueLabel = addTextObject(this.scene, 0, 0, option, setting.default === o ? TextStyle.SETTINGS_SELECTED : TextStyle.WINDOW); + const valueLabel = addTextObject(this.scene, 0, 0, option.label, setting.default === o ? TextStyle.SETTINGS_SELECTED : TextStyle.WINDOW); valueLabel.setOrigin(0, 0); this.optionsContainer.add(valueLabel); diff --git a/src/ui/settings/navigationMenu.ts b/src/ui/settings/navigationMenu.ts index eb65ea95e0c..370b6f67c76 100644 --- a/src/ui/settings/navigationMenu.ts +++ b/src/ui/settings/navigationMenu.ts @@ -4,6 +4,7 @@ import {InputsIcons} from "#app/ui/settings/abstract-control-settings-ui-handler import {addTextObject, setTextStyle, TextStyle} from "#app/ui/text"; import {addWindow} from "#app/ui/ui-theme"; import {Button} from "#enums/buttons"; +import i18next from "i18next"; const LEFT = "LEFT"; const RIGHT = "RIGHT"; @@ -32,7 +33,7 @@ export class NavigationManager { Mode.SETTINGS_GAMEPAD, Mode.SETTINGS_KEYBOARD, ]; - this.labels = ["General", "Display", "Audio", "Gamepad", "Keyboard"]; + this.labels = [i18next.t("settings:general"), i18next.t("settings:display"), i18next.t("settings:audio"), i18next.t("settings:gamepad"), i18next.t("settings:keyboard")]; } public reset() { diff --git a/src/ui/settings/settings-display-ui-handler.ts b/src/ui/settings/settings-display-ui-handler.ts index 0aed0689388..a0c59efdc06 100644 --- a/src/ui/settings/settings-display-ui-handler.ts +++ b/src/ui/settings/settings-display-ui-handler.ts @@ -25,34 +25,64 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler const currentLocale = localStorage.getItem("prLang"); switch (currentLocale) { case "en": - this.settings[languageIndex].options[0] = "English"; + this.settings[languageIndex].options[0] = { + value: "English", + label: "English", + }; break; case "es": - this.settings[languageIndex].options[0] = "Español"; + this.settings[languageIndex].options[0] = { + value: "Español", + label: "Español", + }; break; case "it": - this.settings[languageIndex].options[0] = "Italiano"; + this.settings[languageIndex].options[0] = { + value: "Italiano", + label: "Italiano", + }; break; case "fr": - this.settings[languageIndex].options[0] = "Français"; + this.settings[languageIndex].options[0] = { + value: "Français", + label: "Français", + }; break; case "de": - this.settings[languageIndex].options[0] = "Deutsch"; + this.settings[languageIndex].options[0] = { + value: "Deutsch", + label: "Deutsch", + }; break; case "pt-BR": - this.settings[languageIndex].options[0] = "Português (BR)"; + this.settings[languageIndex].options[0] = { + value: "Português (BR)", + label: "Português (BR)", + }; break; case "zh-CN": - this.settings[languageIndex].options[0] = "简体中文"; + this.settings[languageIndex].options[0] = { + value: "简体中文", + label: "简体中文", + }; break; case "zh-TW": - this.settings[languageIndex].options[0] = "繁體中文"; + this.settings[languageIndex].options[0] = { + value: "繁體中文", + label: "繁體中文", + }; break; case "ko": - this.settings[languageIndex].options[0] = "한국어"; + this.settings[languageIndex].options[0] = { + value: "한국어", + label: "한국어", + }; break; default: - this.settings[languageIndex].options[0] = "English"; + this.settings[languageIndex].options[0] = { + value: "English", + label: "English", + }; break; } } diff --git a/src/ui/settings/settings-gamepad-ui-handler.ts b/src/ui/settings/settings-gamepad-ui-handler.ts index 18ebde962f1..f86e8088ec6 100644 --- a/src/ui/settings/settings-gamepad-ui-handler.ts +++ b/src/ui/settings/settings-gamepad-ui-handler.ts @@ -15,6 +15,7 @@ import {InterfaceConfig} from "#app/inputs-controller"; import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler.js"; import {Device} from "#enums/devices"; import {truncateString} from "#app/utils"; +import i18next from "i18next"; /** * Class representing the settings UI handler for gamepads. @@ -54,7 +55,7 @@ export default class SettingsGamepadUiHandler extends AbstractControlSettingsUiH this.layout["noGamepads"] = new Map(); const optionsContainer = this.scene.add.container(0, 0); optionsContainer.setVisible(false); // Initially hide the container as no gamepads are connected. - const label = addTextObject(this.scene, 8, 28, "Please plug a controller or press a button", TextStyle.SETTINGS_LABEL); + const label = addTextObject(this.scene, 8, 28, i18next.t("settings:gamepadPleasePlug"), TextStyle.SETTINGS_LABEL); label.setOrigin(0, 0); optionsContainer.add(label); this.settingsContainer.add(optionsContainer); diff --git a/src/ui/settings/settings-keyboard-ui-handler.ts b/src/ui/settings/settings-keyboard-ui-handler.ts index 7eb1e4f6c60..5c4444991ad 100644 --- a/src/ui/settings/settings-keyboard-ui-handler.ts +++ b/src/ui/settings/settings-keyboard-ui-handler.ts @@ -15,6 +15,7 @@ import {addTextObject, TextStyle} from "#app/ui/text"; import {deleteBind} from "#app/configs/inputs/configHandler"; import {Device} from "#enums/devices"; import {NavigationManager} from "#app/ui/settings/navigationMenu"; +import i18next from "i18next"; /** * Class representing the settings UI handler for keyboards. @@ -58,7 +59,7 @@ export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUi this.layout["noKeyboard"] = new Map(); const optionsContainer = this.scene.add.container(0, 0); optionsContainer.setVisible(false); // Initially hide the container as no gamepads are connected. - const label = addTextObject(this.scene, 8, 28, "Please press a key on your keyboard", TextStyle.SETTINGS_LABEL); + const label = addTextObject(this.scene, 8, 28, i18next.t("settings:keyboardPleasePress"), TextStyle.SETTINGS_LABEL); label.setOrigin(0, 0); optionsContainer.add(label); this.settingsContainer.add(optionsContainer); @@ -68,7 +69,7 @@ export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUi iconDelete.setPositionRelative(this.actionsBg, this.navigationContainer.width - 260, 4); this.navigationIcons["BUTTON_DELETE"] = iconDelete; - const deleteText = addTextObject(this.scene, 0, 0, "Delete", TextStyle.SETTINGS_LABEL); + const deleteText = addTextObject(this.scene, 0, 0, i18next.t("settings:delete"), TextStyle.SETTINGS_LABEL); deleteText.setOrigin(0, 0.15); deleteText.setPositionRelative(iconDelete, -deleteText.width/6-2, 0); diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 0aa71de7e90..2dd77b53ae0 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -17,7 +17,7 @@ import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, g import { Type } from "../data/type"; import { GameModes } from "../game-mode"; import { SelectChallengePhase, TitlePhase } from "../phases"; -import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterFormMoveData, StarterMoveset } from "../system/game-data"; +import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterFormMoveData, StarterMoveset, StarterAttributes, StarterPreferences, StarterPrefs } from "../system/game-data"; import { Tutorial, handleTutorial } from "../tutorial"; import * as Utils from "../utils"; import { OptionSelectItem } from "./abstact-option-select-ui-handler"; @@ -270,6 +270,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private starterSelectCallback: StarterSelectCallback; + private starterPreferences: StarterPreferences; + protected blockInput: boolean = false; constructor(scene: BattleScene) { @@ -780,6 +782,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } show(args: any[]): boolean { + if (!this.starterPreferences) { + // starterPreferences haven't been loaded yet + this.starterPreferences = StarterPrefs.load(); + } this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers if (args.length >= 1 && args[0] instanceof Function) { super.show(args); @@ -1091,7 +1097,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const species = this.genSpecies[this.getGenCursorWithScroll()][this.cursor]; const isValidForChallenge = new Utils.BooleanHolder(true); - Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge); + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), this.starterGens.length); if (!isDupe && isValidForChallenge.value && this.tryUpdateValue(this.scene.gameData.getSpeciesStarterValue(species.speciesId))) { const cursorObj = this.starterCursorObjs[this.starterCursors.length]; @@ -1223,6 +1229,54 @@ export default class StarterSelectUiHandler extends MessageUiHandler { }); } const starterData = this.scene.gameData.starterData[this.lastSpecies.speciesId]; + let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; + if (this.canCycleNature) { + // if we could cycle natures, enable the improved nature menu + const showNatureOptions = () => { + ui.setMode(Mode.STARTER_SELECT).then(() => { + ui.showText(i18next.t("starterSelectUiHandler:selectNature"), null, () => { + const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry.natureAttr); + ui.setModeWithoutClear(Mode.OPTION_SELECT, { + options: natures.map((n: Nature, i: number) => { + const option: OptionSelectItem = { + label: getNatureName(n, true, true, true, this.scene.uiTheme), + handler: () => { + // update default nature in starter save data + if (!starterAttributes) { + starterAttributes= + this.starterPreferences[this.lastSpecies.speciesId] = {}; + } + starterAttributes.nature = n as unknown as integer; + this.clearText(); + ui.setMode(Mode.STARTER_SELECT); + // set nature for starter + this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, n, undefined); + return true; + } + }; + return option; + }).concat({ + label: i18next.t("menu:cancel"), + handler: () => { + this.clearText(); + ui.setMode(Mode.STARTER_SELECT); + return true; + } + }), + maxOptions: 8, + yOffset: 19 + }); + }); + }); + }; + options.push({ + label: i18next.t("starterSelectUiHandler:manageNature"), + handler: () => { + showNatureOptions(); + return true; + } + }); + } const candyCount = starterData.candyCount; const passiveAttr = starterData.passiveAttr; if (passiveAttr & PassiveAttr.UNLOCKED) { @@ -1362,9 +1416,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const rows = Math.ceil(genStarters / 9); const row = Math.floor(this.cursor / 9); const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor); + // prepare persistent starter data to store changes + let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; + if (!starterAttributes) { + starterAttributes = + this.starterPreferences[this.lastSpecies.speciesId] = {}; + } switch (button) { case Button.CYCLE_SHINY: if (this.canCycleShiny) { + starterAttributes.variant = !props.shiny ? props.variant : -1; // update shiny setting this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined); if (this.dexAttrCursor & DexAttr.SHINY) { this.scene.playSound("sparkle"); @@ -1383,12 +1444,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler { break; } } while (newFormIndex !== props.formIndex); + starterAttributes.form = newFormIndex; // store the selected form this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined, undefined); success = true; } break; case Button.CYCLE_GENDER: if (this.canCycleGender) { + starterAttributes.female = !props.female; this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined, undefined); success = true; } @@ -1414,6 +1477,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } } while (newAbilityIndex !== this.abilityCursor); + starterAttributes.ability = newAbilityIndex; // store the selected ability this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newAbilityIndex, undefined); success = true; } @@ -1423,6 +1487,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry.natureAttr); const natureIndex = natures.indexOf(this.natureCursor); const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0]; + // store cycled nature as default + starterAttributes.nature = newNature as unknown as integer; this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, newNature, undefined); success = true; } @@ -1446,6 +1512,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } } while (newVariant !== props.variant); + starterAttributes.variant = newVariant; // store the selected variant this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant, undefined, undefined); // Cycle tint based on current sprite tint @@ -1782,6 +1849,60 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0; this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0; + const starterAttributes : StarterAttributes = species ? {...this.starterPreferences[species.speciesId]} : null; + // validate starterAttributes + if (starterAttributes) { + // this may cause changes so we created a copy of the attributes before + if (!isNaN(starterAttributes.variant)) { + if (![ + this.speciesStarterDexEntry.caughtAttr & DexAttr.NON_SHINY, + this.speciesStarterDexEntry.caughtAttr & DexAttr.DEFAULT_VARIANT, + this.speciesStarterDexEntry.caughtAttr & DexAttr.VARIANT_2, + this.speciesStarterDexEntry.caughtAttr & DexAttr.VARIANT_3 + ][starterAttributes.variant+1]) { // add 1 as -1 = non-shiny + // requested variant wasn't unlocked, purging setting + delete starterAttributes.variant; + } + } + + if (typeof starterAttributes.female !== "boolean" || !(starterAttributes.female ? + this.speciesStarterDexEntry.caughtAttr & DexAttr.FEMALE : + this.speciesStarterDexEntry.caughtAttr & DexAttr.MALE + )) { + // requested gender wasn't unlocked, purging setting + delete starterAttributes.female; + } + + const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr; + if (![ + abilityAttr & AbilityAttr.ABILITY_1, + species.ability2 ? (abilityAttr & AbilityAttr.ABILITY_2) : abilityAttr & AbilityAttr.ABILITY_HIDDEN, + species.ability2 && abilityAttr & AbilityAttr.ABILITY_HIDDEN + ][starterAttributes.ability]) { + // requested ability wasn't unlocked, purging setting + delete starterAttributes.ability; + } + + if (!(species.forms[starterAttributes.form]?.isStarterSelectable && this.speciesStarterDexEntry.caughtAttr & this.scene.gameData.getFormAttr(starterAttributes.form))) { + // requested form wasn't unlocked/isn't a starter form, purging setting + delete starterAttributes.form; + } + + if (this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry.natureAttr).indexOf(starterAttributes.nature as unknown as Nature) < 0) { + // requested nature wasn't unlocked, purging setting + delete starterAttributes.nature; + } + } + + if (starterAttributes?.nature) { + // load default nature from stater save data, if set + this.natureCursor = starterAttributes.nature; + } + if (!isNaN(starterAttributes?.ability)) { + // load default nature from stater save data, if set + this.abilityCursor = starterAttributes.ability; + } + if (this.statsMode) { if (this.speciesStarterDexEntry?.caughtAttr) { this.statsContainer.setVisible(true); @@ -1854,6 +1975,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonHatchedIcon, this.pokemonHatchedCountText ].map(c => c.setVisible(false)); + this.pokemonFormText.setY(25); } else if (species.speciesId === Species.ETERNATUS) { this.pokemonHatchedIcon.setVisible(false); this.pokemonHatchedCountText.setVisible(false); @@ -1867,6 +1989,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonCandyCountText.setText(`x${this.scene.gameData.starterData[species.speciesId].candyCount}`); this.pokemonCandyCountText.setVisible(true); this.pokemonFormText.setVisible(true); + this.pokemonFormText.setY(42); this.pokemonHatchedIcon.setVisible(true); this.pokemonHatchedCountText.setVisible(true); @@ -1920,9 +2043,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, this.starterAbilityIndexes[starterIndex], this.starterNatures[starterIndex]); } else { const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true); - const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); - const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species); + const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); + // load default nature from stater save data, if set + const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species); props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); + if (!isNaN(starterAttributes?.variant)) { + if (props.shiny = (starterAttributes.variant >= 0)) { + props.variant = starterAttributes.variant as Variant; + } + } + props.formIndex = starterAttributes?.form ?? props.formIndex; + props.female = starterAttributes?.female ?? props.female; this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, defaultAbilityIndex, defaultNature); } @@ -2085,8 +2216,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonSprite.setVisible(!this.statsMode); }); - (this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite) - .setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female, formIndex, shiny, variant)); + + const isValidForChallenge = new Utils.BooleanHolder(true); + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), this.starterGens.length); + const starterSprite = this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite; + starterSprite.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female, formIndex, shiny, variant)); + starterSprite.setAlpha(isValidForChallenge.value ? 1 : 0.375); this.checkIconId((this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite), species, female, formIndex, shiny, variant); this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY); this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE); @@ -2303,7 +2438,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { * we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too. */ const isValidForChallenge = new Utils.BooleanHolder(true); - Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.genSpecies[g][s], isValidForChallenge); + Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.genSpecies[g][s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.genSpecies[g][s], this.scene.gameData.getSpeciesDefaultDexAttr(this.genSpecies[g][s], false, true)), this.starterGens.length + (add ? 1 : 0)); const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value; @@ -2417,6 +2552,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler { clear(): void { super.clear(); + + StarterPrefs.save(this.starterPreferences); this.cursor = -1; this.hideInstructions(); this.starterSelectContainer.setVisible(false); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 5b4dc2cf84f..73edda0ba44 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -15,7 +15,7 @@ import { Stat, getStatName } from "../data/pokemon-stat"; import { PokemonHeldItemModifier } from "../modifier/modifier"; import { StatusEffect } from "../data/status-effect"; import { getBiomeName } from "../data/biomes"; -import { Nature, getNatureStatMultiplier } from "../data/nature"; +import { getNatureName, getNatureStatMultiplier } from "../data/nature"; import { loggedInUser } from "../account"; import { Variant, getVariantTint } from "#app/data/variant"; import {Button} from "#enums/buttons"; @@ -796,7 +796,7 @@ export default class SummaryUiHandler extends UiHandler { this.passiveContainer?.nameText.setVisible(false); this.passiveContainer?.descriptionText.setVisible(false); - const memoString = `${getBBCodeFrag(Utils.toReadableString(Nature[this.pokemon.getNature()]), TextStyle.SUMMARY_RED)}${getBBCodeFrag(" nature,", TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(`${this.pokemon.metBiome === -1 ? "apparently " : ""}met at Lv`, TextStyle.WINDOW_ALT)}${getBBCodeFrag(this.pokemon.metLevel.toString(), TextStyle.SUMMARY_RED)}${getBBCodeFrag(",", TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(getBiomeName(this.pokemon.metBiome), TextStyle.SUMMARY_RED)}${getBBCodeFrag(".", TextStyle.WINDOW_ALT)}`; + const memoString = `${getBBCodeFrag(Utils.toReadableString(getNatureName(this.pokemon.getNature())), TextStyle.SUMMARY_RED)}${getBBCodeFrag(" nature,", TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(`${this.pokemon.metBiome === -1 ? "apparently " : ""}met at Lv`, TextStyle.WINDOW_ALT)}${getBBCodeFrag(this.pokemon.metLevel.toString(), TextStyle.SUMMARY_RED)}${getBBCodeFrag(",", TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(getBiomeName(this.pokemon.metBiome), TextStyle.SUMMARY_RED)}${getBBCodeFrag(".", TextStyle.WINDOW_ALT)}`; const memoText = addBBCodeTextObject(this.scene, 7, 113, memoString, TextStyle.WINDOW_ALT); memoText.setOrigin(0, 0); diff --git a/src/ui/unavailable-modal-ui-handler.ts b/src/ui/unavailable-modal-ui-handler.ts index 60d01a93c82..cddcde2a1b3 100644 --- a/src/ui/unavailable-modal-ui-handler.ts +++ b/src/ui/unavailable-modal-ui-handler.ts @@ -3,6 +3,7 @@ import { ModalConfig, ModalUiHandler } from "./modal-ui-handler"; import { addTextObject, TextStyle } from "./text"; import { Mode } from "./ui"; import { updateUserInfo } from "#app/account"; +import * as Utils from "#app/utils"; export default class UnavailableModalUiHandler extends ModalUiHandler { private reconnectTimer: NodeJS.Timeout; @@ -55,6 +56,9 @@ export default class UnavailableModalUiHandler extends ModalUiHandler { this.reconnectDuration = this.minTime; this.scene.playSound("pb_bounce_1"); this.reconnectCallback(); + } else if (response[1] === 401) { + Utils.setCookie(Utils.sessionIdKey, ""); + this.scene.reset(true, true); } else { this.reconnectDuration = Math.min(this.reconnectDuration * 2, this.maxTime); // Set a max delay so it isn't infinite this.reconnectTimer = diff --git a/src/ui/vouchers-ui-handler.ts b/src/ui/vouchers-ui-handler.ts index a57a5dda9e7..370859bed54 100644 --- a/src/ui/vouchers-ui-handler.ts +++ b/src/ui/vouchers-ui-handler.ts @@ -1,6 +1,6 @@ import BattleScene from "../battle-scene"; import { Button } from "#enums/buttons"; -import i18next from "../plugins/i18n"; +import i18next from "i18next"; import { Voucher, getVoucherTypeIcon, getVoucherTypeName, vouchers } from "../system/voucher"; import MessageUiHandler from "./message-ui-handler"; import { TextStyle, addTextObject } from "./text"; diff --git a/tsconfig.json b/tsconfig.json index 353abd27d4f..682b3a7084b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,9 +20,10 @@ "noEmit": true }, "typedocOptions": { - "entryPoints": ["src/"], + "entryPoints": ["./src"], "entryPointStrategy": "expand", - "out": "typedoc", + "exclude": "**/*+.test.ts", + "out": "typedoc" }, "exclude": [ "node_modules",