diff --git a/src/data/ability.ts b/src/data/ability.ts index e02c2afd4f5..2dd3f1687ca 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -752,7 +752,7 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { if (this.condition(pokemon, attacker, move)) { if (!pokemon.getTag(this.tagType)) { pokemon.addTag(this.tagType, undefined, undefined, pokemon.id); - pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.name })); + pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name })); } return true; } @@ -2936,7 +2936,7 @@ export class PostTurnStatusHealAbAttr extends PostTurnAbAttr { const scene = pokemon.scene; const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name; scene.unshiftPhase(new PokemonHealPhase(scene, pokemon.getBattlerIndex(), - Math.max(Math.floor(pokemon.getMaxHp() / 8), 1), i18next.t("abilityTriggers:poisonHeal", { pokemonName: pokemon.name, abilityName: abilityName}), true)); + Math.max(Math.floor(pokemon.getMaxHp() / 8), 1), i18next.t("abilityTriggers:poisonHeal", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName}), true)); return true; } } @@ -3912,7 +3912,7 @@ export class IceFaceBlockPhysicalAbAttr extends ReceivedMoveDamageMultiplierAbAt * @returns {string} - The trigger message. */ getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonName: pokemon.name, abilityName: abilityName }); + return i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName }); } } diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 28d38daffb4..2676826ff63 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -2,7 +2,7 @@ import { Arena } from "../field/arena"; import { Type } from "./type"; import * as Utils from "../utils"; import { MoveCategory, allMoves, MoveTarget } from "./move"; -import { getPokemonMessage } from "../messages"; +import { getPokemonMessage, getPokemonNameWithAffix } from "../messages"; import Pokemon, { HitResult, PokemonMove } from "../field/pokemon"; import { MoveEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases"; import { StatusEffect } from "./status-effect"; @@ -635,7 +635,7 @@ class StealthRockTag extends ArenaTrapTag { if (damageHpRatio) { const damage = Math.ceil(pokemon.getMaxHp() * damageHpRatio); - pokemon.scene.queueMessage(`Pointed stones dug into\n${pokemon.name}!`); + pokemon.scene.queueMessage(`Pointed stones dug into\n${getPokemonNameWithAffix(pokemon)}!`); pokemon.damageAndUpdate(damage, HitResult.OTHER); if (pokemon.turnData) { pokemon.turnData.damageTaken += damage; @@ -677,7 +677,7 @@ class StickyWebTag extends ArenaTrapTag { const cancelled = new Utils.BooleanHolder(false); applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); if (!cancelled.value) { - pokemon.scene.queueMessage(`The opposing ${pokemon.name} was caught in a sticky web!`); + pokemon.scene.queueMessage(`The opposing ${getPokemonNameWithAffix(pokemon)} was caught in a sticky web!`); const statLevels = new Utils.NumberHolder(-1); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [BattleStat.SPD], statLevels.value)); } @@ -759,7 +759,7 @@ class TailwindTag extends ArenaTag { // Apply the CHARGED tag to party members with the WIND_POWER ability if (pokemon.hasAbility(Abilities.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) { pokemon.addTag(BattlerTagType.CHARGED); - pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: this.getMoveName() })); + pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: this.getMoveName() })); } // Raise attack by one stage if party member has WIND_RIDER ability if (pokemon.hasAbility(Abilities.WIND_RIDER)) { diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 00de610b300..5d175ca22ec 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -335,7 +335,7 @@ export class InfatuatedTag extends BattlerTag { pokemon.scene.queueMessage( i18next.t("battle:battlerTagsInfatuatedOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)) }) ); } @@ -353,7 +353,7 @@ export class InfatuatedTag extends BattlerTag { pokemon.scene.queueMessage( i18next.t("battle:battlerTagsInfatuatedLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)) }) ); pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), undefined, CommonAnim.ATTRACT)); @@ -581,7 +581,7 @@ export class HelpingHandTag extends BattlerTag { pokemon.scene.queueMessage( i18next.t("battle:battlerTagsHelpingHandOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)), - pokemonName: pokemon.name + pokemonName: getPokemonNameWithAffix(pokemon) }) ); } @@ -682,7 +682,7 @@ export class AquaRingTag extends BattlerTag { Math.floor(pokemon.getMaxHp() / 16), i18next.t("battle:battlerTagsAquaRingLapse", { moveName: this.getMoveName(), - pokemonName: pokemon.name + pokemonName: getPokemonNameWithAffix(pokemon) }), true)); } @@ -801,7 +801,7 @@ export class BindTag extends DamagingTrapTag { getTrapMessage(pokemon: Pokemon): string { return i18next.t("battle:battlerTagsBindOnTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name, + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)), moveName: this.getMoveName() }); } @@ -815,7 +815,7 @@ export class WrapTag extends DamagingTrapTag { getTrapMessage(pokemon: Pokemon): string { return i18next.t("battle:battlerTagsWrapOnTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - sourcePokemonName: pokemon.scene.getPokemonById(this.sourceId).name + sourcePokemonName: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)) }); } } @@ -850,7 +850,7 @@ export class ClampTag extends DamagingTrapTag { getTrapMessage(pokemon: Pokemon): string { return i18next.t("battle:battlerTagsClampOnTrap", { sourcePokemonNameWithAffix: getPokemonNameWithAffix(pokemon.scene.getPokemonById(this.sourceId)), - pokemonName: pokemon.name, + pokemonName: getPokemonNameWithAffix(pokemon), }); } } diff --git a/src/data/move.ts b/src/data/move.ts index 8b6b94c47a6..eb708c36a73 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1614,11 +1614,11 @@ export class HitHealAttr extends MoveEffectAttr { if (this.healStat) { // Strength Sap formula healAmount = target.getBattleStat(this.healStat); - message = i18next.t("battle:drainMessage", {pokemonName: target.name}); + message = i18next.t("battle:drainMessage", {pokemonName: getPokemonNameWithAffix(target)}); } else { // Default healing formula used by draining moves like Absorb, Draining Kiss, Bitter Blade, etc. healAmount = Math.max(Math.floor(user.turnData.currDamageDealt * this.healRatio), 1); - message = i18next.t("battle:regainHealth", {pokemonName: user.name}); + message = i18next.t("battle:regainHealth", {pokemonName: getPokemonNameWithAffix(user)}); } if (reverseDrain) { user.turnData.damageTaken += healAmount; @@ -2416,7 +2416,7 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr { if (args.length < 2 || !args[1]) { new MoveChargeAnim(this.chargeAnim, move.id, user).play(user.scene, () => { (args[0] as Utils.BooleanHolder).value = true; - user.scene.queueMessage(getPokemonMessage(user, ` ${this.chargeText.replace("{TARGET}", target.name)}`)); + user.scene.queueMessage(getPokemonMessage(user, ` ${this.chargeText.replace("{TARGET}", getPokemonNameWithAffix(target))}`)); user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER }); user.scene.arena.addTag(this.tagType, 3, move.id, user.id, ArenaTagSide.BOTH, false, target.getBattlerIndex()); @@ -4128,7 +4128,7 @@ export class CurseAttr extends MoveEffectAttr { user.scene.queueMessage( i18next.t("battle:battlerTagsCursedOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(user), - pokemonName: target.name + pokemonName: getPokemonNameWithAffix(target) }) ); @@ -4536,7 +4536,7 @@ export class SwapArenaTagsAttr extends MoveEffectAttr { } - user.scene.queueMessage( `${user.name} swapped the battle effects affecting each side of the field!`); + user.scene.queueMessage( `${getPokemonNameWithAffix(user)} swapped the battle effects affecting each side of the field!`); return true; } } @@ -4577,7 +4577,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { const slotIndex = user.scene.getEnemyParty().findIndex(p => pokemon.id === p.id); pokemon.resetStatus(); pokemon.heal(Math.min(Math.max(Math.ceil(Math.floor(0.5 * pokemon.getMaxHp())), 1), pokemon.getMaxHp())); - user.scene.queueMessage(`${pokemon.name} was revived!`,0,true); + user.scene.queueMessage(`${getPokemonNameWithAffix(pokemon)} was revived!`,0,true); if (user.scene.currentBattle.double && user.scene.getEnemyParty().length > 1) { const allyPokemon = user.getAlly(); @@ -4768,7 +4768,7 @@ export class CopyTypeAttr extends MoveEffectAttr { user.summonData.types = target.getTypes(true); user.updateInfo(); - user.scene.queueMessage(getPokemonMessage(user, `'s type\nchanged to match ${target.name}'s!`)); + user.scene.queueMessage(getPokemonMessage(user, `'s type\nchanged to match ${getPokemonNameWithAffix(target)}'s!`)); return true; } @@ -5150,7 +5150,7 @@ export class ReducePpMoveAttr extends MoveEffectAttr { const lastPpUsed = movesetMove.ppUsed; 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}); + const message = i18next.t("battle:ppReduced", {targetName: getPokemonNameWithAffix(target), moveName: movesetMove.getName(), reduction: movesetMove.ppUsed - lastPpUsed}); user.scene.queueMessage(message); diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index ae1532f0be0..2c2d637c6f0 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -8,6 +8,7 @@ import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import { TimeOfDay } from "#enums/time-of-day"; +import { getPokemonNameWithAffix } from "#app/messages.js"; export enum FormChangeItem { NONE, @@ -369,7 +370,7 @@ export function getSpeciesFormChangeMessage(pokemon: Pokemon, formChange: Specie return `${prefix}${preName} Eternamaxed\ninto ${pokemon.name}!`; } if (isRevert) { - return `${prefix}${pokemon.name} reverted\nto its original form!`; + return `${prefix}${getPokemonNameWithAffix(pokemon)} reverted\nto its original form!`; } return `${prefix}${preName} changed form!`; } diff --git a/src/egg-hatch-phase.ts b/src/egg-hatch-phase.ts index 44b72fb3d05..3965eae74f6 100644 --- a/src/egg-hatch-phase.ts +++ b/src/egg-hatch-phase.ts @@ -11,6 +11,7 @@ import { achvs } from "./system/achv"; import PokemonInfoContainer from "./ui/pokemon-info-container"; import EggCounterContainer from "./ui/egg-counter-container"; import { EggCountChangedEvent } from "./events/egg"; +import { getPokemonNameWithAffix } from "./messages"; /** * Class that represents egg hatching @@ -342,7 +343,7 @@ export class EggHatchPhase extends Phase { this.scene.playSoundWithoutBgm("evolution_fanfare"); - this.scene.ui.showText(i18next.t("egg:hatchFromTheEgg", { pokemonName: this.pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("egg:hatchFromTheEgg", { pokemonName: getPokemonNameWithAffix(this.pokemon) }), null, () => { this.scene.gameData.updateSpeciesDexIvs(this.pokemon.species.speciesId, this.pokemon.ivs); this.scene.gameData.setPokemonCaught(this.pokemon, true, true).then(() => { this.scene.gameData.setEggMoveUnlocked(this.pokemon.species, this.eggMoveIndex).then(() => { diff --git a/src/evolution-phase.ts b/src/evolution-phase.ts index c7986f6664f..28edeee1a77 100644 --- a/src/evolution-phase.ts +++ b/src/evolution-phase.ts @@ -10,6 +10,7 @@ import { cos, sin } from "./field/anims"; import { PlayerPokemon } from "./field/pokemon"; import { getTypeRgb } from "./data/type"; import i18next from "i18next"; +import { getPokemonNameWithAffix } from "./messages"; export class EvolutionPhase extends Phase { protected pokemon: PlayerPokemon; @@ -116,7 +117,7 @@ export class EvolutionPhase extends Phase { doEvolution(): void { const evolutionHandler = this.scene.ui.getHandler() as EvolutionSceneHandler; - const preName = this.pokemon.name; + const preName = getPokemonNameWithAffix(this.pokemon); this.scene.ui.showText(i18next.t("menu:evolving", { pokemonName: preName }), null, () => { this.pokemon.cry(); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 44e9cdf18d7..2fe1d831659 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -50,6 +50,7 @@ import { BerryType } from "#enums/berry-type"; import { Biome } from "#enums/biome"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import { getPokemonNameWithAffix } from "#app/messages.js"; export enum FieldPosition { CENTER, @@ -60,6 +61,7 @@ export enum FieldPosition { export default abstract class Pokemon extends Phaser.GameObjects.Container { public id: integer; public name: string; + public nickname: string; public species: PokemonSpecies; public formIndex: integer; public abilityIndex: integer; @@ -153,6 +155,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.variant = 0; } this.nature = dataSource.nature || 0 as Nature; + this.nickname = dataSource.nickname; this.natureOverride = dataSource.natureOverride !== undefined ? dataSource.natureOverride : -1; this.moveset = dataSource.moveset; this.status = dataSource.status; @@ -226,6 +229,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.calculateStats(); } + + getNameToRender() { + try { + if (this.nickname) { + return decodeURIComponent(escape(atob(this.nickname))); + } + return this.name; + } catch (err) { + console.error(`Failed to decode nickname for ${this.name}`, err); + return this.name; + } + } + init(): void { this.fieldPosition = FieldPosition.CENTER; @@ -2047,7 +2063,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective")); break; case HitResult.NO_EFFECT: - this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: this.name })); + this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) })); break; case HitResult.IMMUNE: this.scene.queueMessage(`${this.name} is unaffected!`); @@ -2080,7 +2096,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, typeMultiplier)); } if (!typeMultiplier.value) { - this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: this.name })); + this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) })); } result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS; break; diff --git a/src/form-change-phase.ts b/src/form-change-phase.ts index ebf91c635fd..55bf655081b 100644 --- a/src/form-change-phase.ts +++ b/src/form-change-phase.ts @@ -10,6 +10,7 @@ import PartyUiHandler from "./ui/party-ui-handler"; import { BattleSpec } from "#enums/battle-spec"; import { BattlePhase, MovePhase, PokemonHealPhase } from "./phases"; import { getTypeRgb } from "./data/type"; +import { getPokemonNameWithAffix } from "./messages"; export class FormChangePhase extends EvolutionPhase { private formChange: SpeciesFormChange; @@ -34,7 +35,7 @@ export class FormChangePhase extends EvolutionPhase { } doEvolution(): void { - const preName = this.pokemon.name; + const preName = getPokemonNameWithAffix(this.pokemon); this.pokemon.getPossibleForm(this.formChange).then(transformedPokemon => { @@ -191,7 +192,7 @@ export class QuietFormChangePhase extends BattlePhase { return this.end(); } - const preName = this.pokemon.name; + const preName = getPokemonNameWithAffix(this.pokemon); if (!this.pokemon.isOnField()) { this.pokemon.changeForm(this.formChange).then(() => { diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index 01e15fb7629..bfc4c31efcb 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"Nein", "disclaimer": "HAFTUNGSAUSSCHLUSS", "disclaimerDescription": "Dieses Spiel ist ein unfertiges Produkt. Es kann spielbeinträchtigende Fehler (bis hin zum Verlust des Speicherstandes)\n aufweisen, sich ohne Vorankündigung ändern und es gibt keine Garantie dass es weiterentwickelt oder fertiggestellt wird.", + "choosePokemon": "Wähle ein Pokémon.", + "renamePokemon": "Pokémon umbennenen", + "rename": "Umbenennen", + "nickname": "Spitzname", "errorServerDown": "Ups! Es gab einen Fehler beim Versuch\nden Server zu kontaktieren\nLasse dieses Fenster offen\nDu wirst automatisch neu verbunden.", } as const; diff --git a/src/locales/de/party-ui-handler.ts b/src/locales/de/party-ui-handler.ts index 604efb83628..097b670c768 100644 --- a/src/locales/de/party-ui-handler.ts +++ b/src/locales/de/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Stafette nutzen", "UNPAUSE_EVOLUTION": "Entwicklung fortsetzen", "REVIVE": "Wiederbeleben", + "RENAME": "Umbenennen", "choosePokemon": "Wähle ein Pokémon.", "doWhatWithThisPokemon": "Was soll mit diesem Pokémon geschehen?", diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index c6a767def50..fe4d96c5120 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "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.", + "choosePokemon": "Choose a Pokémon.", + "renamePokemon": "Rename Pokémon", + "rename": "Rename", + "nickname": "Nickname", "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect.", } as const; diff --git a/src/locales/en/party-ui-handler.ts b/src/locales/en/party-ui-handler.ts index 78fdcc14dbe..4f300dd36ea 100644 --- a/src/locales/en/party-ui-handler.ts +++ b/src/locales/en/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Pass Baton", "UNPAUSE_EVOLUTION": "Unpause Evolution", "REVIVE": "Revive", + "RENAME": "Rename", "choosePokemon": "Choose a Pokémon.", "doWhatWithThisPokemon": "Do what with this Pokémon?", diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 524464f32f7..55bd9c6c038 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"No", "disclaimer": "AVISO", "disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida\n de datos de guardado),cambiar sin avisar, y puede o no puede ser actualizado hasta ser completado.", + "choosePokemon": "Choose a Pokémon.", + "renamePokemon": "Rename Pokémon", + "rename": "Rename", + "nickname": "Nickname", "errorServerDown": "¡Ups! Ha habido un problema al contactar con el servidor.\n\nPuedes mantener esta ventana abierta,\nel juego se reconectará automáticamente.", } as const; diff --git a/src/locales/es/party-ui-handler.ts b/src/locales/es/party-ui-handler.ts index b310a98840d..cbbd6734b62 100644 --- a/src/locales/es/party-ui-handler.ts +++ b/src/locales/es/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Relevo", "UNPAUSE_EVOLUTION": "Reanudar Evolución", "REVIVE": "Revivir", + "RENAME": "Rename", "choosePokemon": "Elige a un Pokémon.", "doWhatWithThisPokemon": "¿Que quieres hacer con este Pokémon?", diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index aeb6ad9ed7e..41927f83b1c 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -49,5 +49,9 @@ export const menu: SimpleTranslationEntries = { "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é.", + "choosePokemon": "Sélectionnez un Pokémon.", + "renamePokemon": "Renommer Pokémon", + "rename": "Renommer", + "nickname": "Surnom", "errorServerDown": "Oupsi ! Un problème de connexion au serveur est survenu.\n\nVous pouvez garder cette fenêtre ouverte,\nle jeu se reconnectera automatiquement.", } as const; diff --git a/src/locales/fr/party-ui-handler.ts b/src/locales/fr/party-ui-handler.ts index b1324f52398..158a6e8416a 100644 --- a/src/locales/fr/party-ui-handler.ts +++ b/src/locales/fr/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Relais", "UNPAUSE_EVOLUTION": "Réactiver Évolution", "REVIVE": "Ranimer", + "RENAME": "Renommer", "choosePokemon": "Sélectionnez un Pokémon.", "doWhatWithThisPokemon": "Que faire avec ce Pokémon ?", diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 8df8c2db9b3..9766708f7ae 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "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.", - "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect.", + "choosePokemon": "Scegli un Pokémon.", + "renamePokemon": "Rinomina un Pokémon", + "rename": "Rinomina", + "nickname": "Nickname", + "errorServerDown": "Poffarbacco! C'è stato un errore nella comunicazione col server.\n\nPuoi lasciare questa finestra aperta,\nil gioco si riconnetterà automaticamente.", } as const; diff --git a/src/locales/it/party-ui-handler.ts b/src/locales/it/party-ui-handler.ts index 86966a6e7f9..979e04f3ea1 100644 --- a/src/locales/it/party-ui-handler.ts +++ b/src/locales/it/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Pass Baton", "UNPAUSE_EVOLUTION": "Unpause Evolution", "REVIVE": "Revive", + "RENAME": "Rinomina", "choosePokemon": "Choose a Pokémon.", "doWhatWithThisPokemon": "Do what with this Pokémon?", diff --git a/src/locales/ko/menu.ts b/src/locales/ko/menu.ts index 1025ccff5c5..368627b0d5d 100644 --- a/src/locales/ko/menu.ts +++ b/src/locales/ko/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no":"아니오", "disclaimer": "면책 조항", "disclaimerDescription": "이 게임은 완전히 개발되지 않았습니다- (세이브 데이터 소실을 포함) 플레이에 지장을 주는 문제가 생길 수 있으며,\n공지 없이 업데이트가 진행 혹은 중지될 수 있습니다.", + "choosePokemon": "포켓몬을 선택하세요.", + "renamePokemon": "포켓몬의 닉네임은?", + "rename": "닉네임 바꾸기", + "nickname": "닉네임", "errorServerDown": "서버 연결 중 문제가 발생했습니다.\n\n이 창을 종료하지 않고 두면,\n게임은 자동으로 재접속됩니다.", } as const; diff --git a/src/locales/ko/party-ui-handler.ts b/src/locales/ko/party-ui-handler.ts index f0075809345..ff5d81eeb52 100644 --- a/src/locales/ko/party-ui-handler.ts +++ b/src/locales/ko/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "배턴터치한다", "UNPAUSE_EVOLUTION": "진화 재개", "REVIVE": "되살린다", + "RENAME": "닉네임 바꾸기", "choosePokemon": "포켓몬을 선택하세요.", "doWhatWithThisPokemon": "포켓몬을 어떻게 하겠습니까?", diff --git a/src/locales/pt_BR/menu.ts b/src/locales/pt_BR/menu.ts index aca16b6b511..927ccce518b 100644 --- a/src/locales/pt_BR/menu.ts +++ b/src/locales/pt_BR/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no": "Não", "disclaimer": "AVISO", "disclaimerDescription": "Este jogo é um produto inacabado; ele pode ter problemas de jogabilidade (incluindo possíveis\n perdas de dados salvos), sofrer alterações sem aviso prévio e pode ou não ser atualizado ou concluído.", + "choosePokemon": "Escolha um Pokémon.", + "renamePokemon": "Renomear Pokémon", + "rename": "Renomear", + "nickname": "Apelido", "errorServerDown": "Opa! Não foi possível conectar-se ao servidor.\n\nVocê pode deixar essa janela aberta,\npois o jogo irá se reconectar automaticamente.", } as const; diff --git a/src/locales/pt_BR/party-ui-handler.ts b/src/locales/pt_BR/party-ui-handler.ts index aac9e56aefa..08132b4bfc0 100644 --- a/src/locales/pt_BR/party-ui-handler.ts +++ b/src/locales/pt_BR/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Passar Bastão", "UNPAUSE_EVOLUTION": "Ativar Evolução", "REVIVE": "Reviver", + "RENAME": "Renomear", "choosePokemon": "Escolha um Pokémon.", "doWhatWithThisPokemon": "O que você deseja fazer?", diff --git a/src/locales/zh_CN/menu.ts b/src/locales/zh_CN/menu.ts index b1b5b00d554..4ff4ffc3128 100644 --- a/src/locales/zh_CN/menu.ts +++ b/src/locales/zh_CN/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "no": "否", "disclaimer": "免责声明", "disclaimerDescription": "这个游戏尚未完成; 可能存在游戏性问题(包括潜在的丢档风险)、\n 不经通知的调整、 未来可能会更新或完成更多内容", + "choosePokemon": "选择一只宝可梦。", + "renamePokemon": "给宝可梦起名", + "rename": "起名", + "nickname": "昵称", "errorServerDown": "糟糕!访问服务器时发生了错误。\n\n你可以保持页面开启,\n游戏会自动重新连接。", } as const; diff --git a/src/locales/zh_CN/party-ui-handler.ts b/src/locales/zh_CN/party-ui-handler.ts index 4cb2f816b2e..7d70ddd1503 100644 --- a/src/locales/zh_CN/party-ui-handler.ts +++ b/src/locales/zh_CN/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "接棒", "UNPAUSE_EVOLUTION": "解除进化暂停", "REVIVE": "复活", + "RENAME": "起名", "choosePokemon": "选择一只宝可梦。", "doWhatWithThisPokemon": "要对宝可梦做什么?", diff --git a/src/locales/zh_TW/menu.ts b/src/locales/zh_TW/menu.ts index e43264de2f6..d46f3f172de 100644 --- a/src/locales/zh_TW/menu.ts +++ b/src/locales/zh_TW/menu.ts @@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = { "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.", + "choosePokemon": "Choose a Pokémon.", + "renamePokemon": "Rename Pokémon", + "rename": "Rename", + "nickname": "Nickname", "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect.", } as const; diff --git a/src/locales/zh_TW/party-ui-handler.ts b/src/locales/zh_TW/party-ui-handler.ts index efa9b2c8dab..c981e41af0e 100644 --- a/src/locales/zh_TW/party-ui-handler.ts +++ b/src/locales/zh_TW/party-ui-handler.ts @@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = { "PASS_BATON": "Pass Baton", "UNPAUSE_EVOLUTION": "Unpause Evolution", "REVIVE": "Revive", + "RENAME": "Rename", "choosePokemon": "Choose a Pokémon.", "doWhatWithThisPokemon": "Do what with this Pokémon?", diff --git a/src/messages.ts b/src/messages.ts index 5c465cc08e9..2259e78abfc 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -24,17 +24,17 @@ export function getPokemonNameWithAffix(pokemon: Pokemon): string { return !pokemon.isPlayer() ? pokemon.hasTrainer() ? i18next.t("battle:foePokemonWithAffix", { - pokemonName: pokemon.name, + pokemonName: pokemon.getNameToRender(), }) : i18next.t("battle:wildPokemonWithAffix", { - pokemonName: pokemon.name, + pokemonName: pokemon.getNameToRender(), }) - : pokemon.name; + : pokemon.getNameToRender(); case BattleSpec.FINAL_BOSS: return !pokemon.isPlayer() - ? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.name }) - : pokemon.name; + ? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() }) + : pokemon.getNameToRender(); default: - return pokemon.name; + return pokemon.getNameToRender(); } } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index d5bbd3b225f..2c69c13a11b 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -27,6 +27,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import { getPokemonNameWithAffix } from "#app/messages.js"; const outputModifierData = false; const useMaxWeightForOutput = false; @@ -212,10 +213,10 @@ export class PokemonHeldItemModifierType extends PokemonModifierType { const matchingModifier = pokemon.scene.findModifier(m => m instanceof Modifiers.PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(dummyModifier)) as Modifiers.PokemonHeldItemModifier; const maxStackCount = dummyModifier.getMaxStackCount(pokemon.scene); if (!maxStackCount) { - return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.inoperable", { "pokemonName": pokemon.name }); + return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.inoperable", { "pokemonName": getPokemonNameWithAffix(pokemon) }); } if (matchingModifier && matchingModifier.stackCount === maxStackCount) { - return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.tooMany", { "pokemonName": pokemon.name }); + return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.tooMany", { "pokemonName": getPokemonNameWithAffix(pokemon) }); } return null; }, group, soundName); diff --git a/src/phases.ts b/src/phases.ts index b39d975d54b..308750cc196 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -869,7 +869,7 @@ export class EncounterPhase extends BattlePhase { loadEnemyAssets.push(enemyPokemon.loadAssets()); - console.log(enemyPokemon.name, enemyPokemon.species.speciesId, enemyPokemon.stats); + console.log(getPokemonNameWithAffix(enemyPokemon), enemyPokemon.species.speciesId, enemyPokemon.stats); }); if (this.scene.getParty().filter(p => p.isShiny()).length === 6) { @@ -971,7 +971,7 @@ 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: getPokemonNameWithAffix(enemyField[0])}); } if (this.scene.currentBattle.battleType === BattleType.TRAINER) { @@ -984,8 +984,8 @@ export class EncounterPhase extends BattlePhase { } 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].getNameToRender() }) + : i18next.t("battle:multiWildAppeared", { pokemonName1: enemyField[0].getNameToRender(), pokemonName2: enemyField[1].getNameToRender() }); } doEncounterCommon(showEncounterMessage: boolean = true) { @@ -1413,11 +1413,11 @@ export class SummonPhase extends PartyMemberPokemonPhase { // Swaps the fainted Pokemon and the first non-fainted legal Pokemon in the party [party[this.partyMemberIndex], party[legalIndex]] = [party[legalIndex], party[this.partyMemberIndex]]; - console.warn("Swapped %s %O with %s %O", partyMember?.name, partyMember, party[0]?.name, party[0]); + console.warn("Swapped %s %O with %s %O", getPokemonNameWithAffix(partyMember), partyMember, getPokemonNameWithAffix(party[0]), party[0]); } if (this.player) { - this.scene.ui.showText(i18next.t("battle:playerGo", { pokemonName: this.getPokemon().name })); + this.scene.ui.showText(i18next.t("battle:playerGo", { pokemonName: getPokemonNameWithAffix(this.getPokemon()) })); if (this.player) { this.scene.pbTray.hide(); } @@ -1437,7 +1437,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { this.scene.time.delayedCall(750, () => this.summon()); } else { const trainerName = this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER); - const pokemonName = this.getPokemon().name; + const pokemonName = getPokemonNameWithAffix(this.getPokemon()); const message = i18next.t("battle:trainerSendOut", { trainerName, pokemonName }); this.scene.pbTrayEnemy.hide(); @@ -1606,10 +1606,10 @@ export class SwitchSummonPhase extends SummonPhase { } this.scene.ui.showText(this.player ? - i18next.t("battle:playerComeBack", { pokemonName: pokemon.name }) : + i18next.t("battle:playerComeBack", { pokemonName: getPokemonNameWithAffix(pokemon) }) : i18next.t("battle:trainerComeBack", { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), - pokemonName: pokemon.name + pokemonName: getPokemonNameWithAffix(pokemon) }) ); this.scene.playSound("pb_rel"); @@ -1649,10 +1649,10 @@ export class SwitchSummonPhase extends SummonPhase { party[this.fieldIndex] = switchedPokemon; const showTextAndSummon = () => { this.scene.ui.showText(this.player ? - i18next.t("battle:playerGo", { pokemonName: switchedPokemon.name }) : + i18next.t("battle:playerGo", { pokemonName: getPokemonNameWithAffix(switchedPokemon) }) : i18next.t("battle:trainerGo", { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), - pokemonName: this.getPokemon().name + pokemonName: getPokemonNameWithAffix(this.getPokemon()) }) ); this.summon(); @@ -1811,7 +1811,7 @@ export class CheckSwitchPhase extends BattlePhase { return; } - this.scene.ui.showText(i18next.t("battle:switchQuestion", { pokemonName: this.useName ? pokemon.name : i18next.t("battle:pokemon") }), null, () => { + this.scene.ui.showText(i18next.t("battle:switchQuestion", { pokemonName: this.useName ? getPokemonNameWithAffix(pokemon) : i18next.t("battle:pokemon") }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); @@ -1831,7 +1831,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: getPokemonNameWithAffix(this.getPokemon()) })); this.scene.time.delayedCall(250, () => this.summon()); } } @@ -1982,7 +1982,7 @@ export class CommandPhase extends FieldPhase { if (!moveId) { turnCommand.targets = [this.fieldIndex]; } - console.log(moveTargets, playerPokemon.name); + console.log(moveTargets, getPokemonNameWithAffix(playerPokemon)); if (moveTargets.targets.length > 1 && moveTargets.multiple) { this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); } @@ -2101,7 +2101,7 @@ export class CommandPhase extends FieldPhase { } this.scene.ui.showText( i18next.t("battle:noEscapePokemon", { - pokemonName: this.scene.getPokemonById(trapTag.sourceId).name, + pokemonName: getPokemonNameWithAffix(this.scene.getPokemonById(trapTag.sourceId)), moveName: trapTag.getMoveName(), escapeVerb: isSwitch ? i18next.t("battle:escapeVerbSwitch") : i18next.t("battle:escapeVerbFlee") }), @@ -4459,7 +4459,7 @@ export class ExpPhase extends PlayerPartyMemberPokemonPhase { const exp = new Utils.NumberHolder(this.expValue); this.scene.applyModifiers(ExpBoosterModifier, true, exp); exp.value = Math.floor(exp.value); - this.scene.ui.showText(i18next.t("battle:expGain", { pokemonName: pokemon.name, exp: exp.value }), null, () => { + this.scene.ui.showText(i18next.t("battle:expGain", { pokemonName: getPokemonNameWithAffix(pokemon), exp: exp.value }), null, () => { const lastLevel = pokemon.level; pokemon.addExp(exp.value); const newLevel = pokemon.level; @@ -4559,7 +4559,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { pokemon.updateInfo(); if (this.scene.expParty === ExpNotification.DEFAULT) { this.scene.playSound("level_up_fanfare"); - this.scene.ui.showText(i18next.t("battle:levelUp", { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); + this.scene.ui.showText(i18next.t("battle:levelUp", { pokemonName: getPokemonNameWithAffix(this.getPokemon()), level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); } else if (this.scene.expParty === ExpNotification.SKIP) { this.end(); } else { @@ -4617,7 +4617,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { .then(() => { this.scene.ui.setMode(messageMode).then(() => { this.scene.playSound("level_up_fanfare"); - this.scene.ui.showText(i18next.t("battle:learnMove", { pokemonName: pokemon.name, moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMove", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => { this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true); this.end(); }, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true); @@ -4626,15 +4626,15 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { }); } else { this.scene.ui.setMode(messageMode).then(() => { - this.scene.ui.showText(i18next.t("battle:learnMovePrompt", { pokemonName: pokemon.name, moveName: move.name }), null, () => { - this.scene.ui.showText(i18next.t("battle:learnMoveLimitReached", { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMovePrompt", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMoveLimitReached", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { this.scene.ui.showText(i18next.t("battle:learnMoveReplaceQuestion", { moveName: move.name }), null, () => { const noHandler = () => { this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.showText(i18next.t("battle:learnMoveStopTeaching", { moveName: move.name }), null, () => { this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setMode(messageMode); - this.scene.ui.showText(i18next.t("battle:learnMoveNotLearned", { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true); + this.scene.ui.showText(i18next.t("battle:learnMoveNotLearned", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }), null, () => this.end(), null, true); }, () => { this.scene.ui.setMode(messageMode); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -4653,7 +4653,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { } this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.showText(i18next.t("battle:countdownPoof"), null, () => { - this.scene.ui.showText(i18next.t("battle:learnMoveForgetSuccess", { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => { + this.scene.ui.showText(i18next.t("battle:learnMoveForgetSuccess", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: pokemon.moveset[moveIndex].getName() }), null, () => { this.scene.ui.showText(i18next.t("battle:learnMoveAnd"), null, () => { pokemon.setMove(moveIndex, Moves.NONE); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -4956,7 +4956,7 @@ export class AttemptCapturePhase extends PokemonPhase { this.scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); - this.scene.ui.showText(i18next.t("battle:pokemonCaught", { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:pokemonCaught", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { const end = () => { this.scene.pokemonInfoContainer.hide(); this.removePb(); @@ -4989,7 +4989,7 @@ export class AttemptCapturePhase extends PokemonPhase { 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, () => { + this.scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { this.scene.pokemonInfoContainer.makeRoomForConfirmUi(); this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.PARTY, PartyUiMode.RELEASE, this.fieldIndex, (slotIndex: integer, _option: PartyOption) => { @@ -5449,7 +5449,7 @@ export class ScanIvsPhase extends PokemonPhase { const pokemon = this.getPokemon(); - this.scene.ui.showText(i18next.t("battle:ivScannerUseQuestion", { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t("battle:ivScannerUseQuestion", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.clearText(); diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 57f4c0aea93..7e8f1e21c07 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -17,6 +17,7 @@ export default class PokemonData { public id: integer; public player: boolean; public species: Species; + public nickname: string; public formIndex: integer; public abilityIndex: integer; public passive: boolean; @@ -59,6 +60,7 @@ export default class PokemonData { this.id = source.id; this.player = sourcePokemon ? sourcePokemon.isPlayer() : source.player; this.species = sourcePokemon ? sourcePokemon.species.speciesId : source.species; + this.nickname = sourcePokemon ? sourcePokemon.nickname : source.nickname; this.formIndex = Math.max(Math.min(source.formIndex, getPokemonSpecies(this.species).forms.length - 1), 0); this.abilityIndex = source.abilityIndex; this.passive = source.passive; @@ -141,7 +143,11 @@ export default class PokemonData { toPokemon(scene: BattleScene, battleType?: BattleType, partyMemberIndex: integer = 0, double: boolean = false): Pokemon { const species = getPokemonSpecies(this.species); const ret: Pokemon = this.player - ? scene.addPlayerPokemon(species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this) + ? scene.addPlayerPokemon(species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this, (playerPokemon) => { + if (this.nickname) { + playerPokemon.nickname = this.nickname; + } + }) : scene.addEnemyPokemon(species, this.level, battleType === BattleType.TRAINER ? !double || !(partyMemberIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER : TrainerSlot.NONE, this.boss, this); if (this.summonData) { ret.primeSummonData(this.summonData); diff --git a/src/ui/ability-bar.ts b/src/ui/ability-bar.ts index a0b249695b9..7a4ae559975 100644 --- a/src/ui/ability-bar.ts +++ b/src/ui/ability-bar.ts @@ -1,3 +1,4 @@ +import { getPokemonNameWithAffix } from "#app/messages.js"; import BattleScene from "../battle-scene"; import Pokemon from "../field/pokemon"; import { TextStyle, addTextObject } from "./text"; @@ -36,7 +37,7 @@ export default class AbilityBar extends Phaser.GameObjects.Container { } showAbility(pokemon: Pokemon, passive: boolean = false): void { - this.abilityBarText.setText(`${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: pokemon.name, passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: !passive ? pokemon.getAbility().name : pokemon.getPassiveAbility().name })}`); + this.abilityBarText.setText(`${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: getPokemonNameWithAffix(pokemon), passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: !passive ? pokemon.getAbility().name : pokemon.getPassiveAbility().name })}`); if (this.shown) { return; diff --git a/src/ui/battle-flyout.ts b/src/ui/battle-flyout.ts index 5b34a6b5411..fdce9661793 100644 --- a/src/ui/battle-flyout.ts +++ b/src/ui/battle-flyout.ts @@ -7,6 +7,7 @@ import { BattleSceneEventType, BerryUsedEvent, MoveUsedEvent } from "../events/b import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { UiTheme } from "#enums/ui-theme"; +import { getPokemonNameWithAffix } from "#app/messages.js"; /** Container for info about a {@linkcode Move} */ interface MoveInfo { @@ -113,8 +114,8 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { initInfo(pokemon: Pokemon) { this.pokemon = pokemon; - this.name = `Flyout ${this.pokemon.name}`; - this.flyoutParent.name = `Flyout Parent ${this.pokemon.name}`; + this.name = `Flyout ${getPokemonNameWithAffix(this.pokemon)}`; + this.flyoutParent.name = `Flyout Parent ${getPokemonNameWithAffix(this.pokemon)}`; this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent); this.battleScene.eventTarget.addEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent); diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index 6d90e0b4fe2..2ac350e2b14 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -278,8 +278,8 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.updateNameText(pokemon); const nameTextWidth = this.nameText.displayWidth; - this.name = pokemon.name; - this.box.name = pokemon.name; + this.name = pokemon.getNameToRender(); + this.box.name = pokemon.getNameToRender(); this.flyoutMenu?.initInfo(pokemon); @@ -507,7 +507,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { return resolve(); } - const nameUpdated = this.lastName !== pokemon.name; + const nameUpdated = this.lastName !== pokemon.getNameToRender(); if (nameUpdated) { this.updateNameText(pokemon); @@ -634,7 +634,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { } updateNameText(pokemon: Pokemon): void { - let displayName = pokemon.name.replace(/[♂♀]/g, ""); + let displayName = pokemon.getNameToRender().replace(/[♂♀]/g, ""); let nameTextWidth: number; const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.BATTLE_INFO); @@ -649,7 +649,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { nameSizeTest.destroy(); this.nameText.setText(displayName); - this.lastName = pokemon.name; + this.lastName = pokemon.getNameToRender(); if (this.nameText.visible) { this.nameText.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.nameText.width, this.nameText.height), Phaser.Geom.Rectangle.Contains); diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index 8ccd05675c8..f083acd2f5b 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -6,6 +6,7 @@ import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import i18next from "i18next"; import {Button} from "#enums/buttons"; +import { getPokemonNameWithAffix } from "#app/messages.js"; export enum Command { FIGHT = 0, @@ -66,7 +67,7 @@ export default class CommandUiHandler extends UiHandler { messageHandler.commandWindow.setVisible(true); messageHandler.movesWindowContainer.setVisible(false); messageHandler.message.setWordWrapWidth(1110); - messageHandler.showText(i18next.t("commandUiHandler:actionMessage", {pokemonName: commandPhase.getPokemon().name}), 0); + messageHandler.showText(i18next.t("commandUiHandler:actionMessage", {pokemonName: getPokemonNameWithAffix(commandPhase.getPokemon())}), 0); this.setCursor(this.getCursor()); return true; diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index c5e369e9193..9bb8162ce2a 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -21,6 +21,7 @@ import MoveInfoOverlay from "./move-info-overlay"; import i18next from "i18next"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import { Moves } from "#enums/moves"; +import { getPokemonNameWithAffix } from "#app/messages.js"; const defaultMessage = i18next.t("partyUiHandler:choosePokemon"); @@ -52,6 +53,7 @@ export enum PartyOption { SPLICE, UNSPLICE, RELEASE, + RENAME, SCROLL_UP = 1000, SCROLL_DOWN = 1001, FORM_CHANGE_ITEM = 2000, @@ -59,7 +61,7 @@ export enum PartyOption { MOVE_2, MOVE_3, MOVE_4, - ALL = 4000 + ALL = 4000, } export type PartySelectCallback = (cursor: integer, option: PartyOption) => void; @@ -115,14 +117,14 @@ export default class PartyUiHandler extends MessageUiHandler { public static FilterNonFainted = (pokemon: PlayerPokemon) => { if (pokemon.isFainted()) { - return i18next.t("partyUiHandler:noEnergy", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:noEnergy", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; public static FilterFainted = (pokemon: PlayerPokemon) => { if (!pokemon.isFainted()) { - return i18next.t("partyUiHandler:hasEnergy", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:hasEnergy", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; @@ -136,7 +138,7 @@ export default class PartyUiHandler extends MessageUiHandler { const challengeAllowed = new Utils.BooleanHolder(true); applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, pokemon, challengeAllowed); if (!challengeAllowed.value) { - return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; @@ -146,14 +148,14 @@ export default class PartyUiHandler extends MessageUiHandler { public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => { const matchingModifier = pokemon.scene.findModifier(m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(modifier)) as PokemonHeldItemModifier; if (matchingModifier && matchingModifier.stackCount === matchingModifier.getMaxStackCount(pokemon.scene)) { - return i18next.t("partyUiHandler:tooManyItems", { pokemonName: pokemon.name }); + return i18next.t("partyUiHandler:tooManyItems", { pokemonName: getPokemonNameWithAffix(pokemon) }); } return null; }; public static NoEffectMessage = i18next.t("partyUiHandler:anyEffect"); - private localizedOptions = [PartyOption.SEND_OUT, PartyOption.SUMMARY, PartyOption.CANCEL, PartyOption.APPLY, PartyOption.RELEASE, PartyOption.TEACH, PartyOption.SPLICE, PartyOption.UNSPLICE, PartyOption.REVIVE, PartyOption.TRANSFER, PartyOption.UNPAUSE_EVOLUTION, PartyOption.PASS_BATON]; + private localizedOptions = [PartyOption.SEND_OUT, PartyOption.SUMMARY, PartyOption.CANCEL, PartyOption.APPLY, PartyOption.RELEASE, PartyOption.TEACH, PartyOption.SPLICE, PartyOption.UNSPLICE, PartyOption.REVIVE, PartyOption.TRANSFER, PartyOption.UNPAUSE_EVOLUTION, PartyOption.PASS_BATON, PartyOption.RENAME]; constructor(scene: BattleScene) { super(scene, Mode.PARTY); @@ -302,7 +304,7 @@ export default class PartyUiHandler extends MessageUiHandler { } ui.playSelect(); return true; - } else if ((option !== PartyOption.SUMMARY && option !== PartyOption.UNPAUSE_EVOLUTION && option !== PartyOption.UNSPLICE && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL) + } else if ((option !== PartyOption.SUMMARY && option !== PartyOption.UNPAUSE_EVOLUTION && option !== PartyOption.UNSPLICE && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL && option !== PartyOption.RENAME) || (option === PartyOption.RELEASE && this.partyUiMode === PartyUiMode.RELEASE)) { let filterResult: string; const getTransferrableItemsFromPokemon = (pokemon: PlayerPokemon) => @@ -378,7 +380,7 @@ export default class PartyUiHandler extends MessageUiHandler { this.clearOptions(); ui.playSelect(); pokemon.pauseEvolutions = false; - this.showText(i18next.t("partyUiHandler:unpausedEvolutions", { pokemonName: pokemon.name }), null, () => this.showText(null, 0), null, true); + this.showText(i18next.t("partyUiHandler:unpausedEvolutions", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => this.showText(null, 0), null, true); } else if (option === PartyOption.UNSPLICE) { this.clearOptions(); ui.playSelect(); @@ -403,7 +405,7 @@ export default class PartyUiHandler extends MessageUiHandler { this.clearOptions(); ui.playSelect(); if (this.cursor >= this.scene.currentBattle.getBattlerCount() || !pokemon.isAllowedInBattle()) { - this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: pokemon.name }), null, () => { + this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { ui.setModeWithoutClear(Mode.CONFIRM, () => { ui.setMode(Mode.PARTY); this.doRelease(this.cursor); @@ -416,6 +418,25 @@ export default class PartyUiHandler extends MessageUiHandler { this.showText(i18next.t("partyUiHandler:releaseInBattle"), null, () => this.showText(null, 0), null, true); } return true; + } else if (option === PartyOption.RENAME) { + this.clearOptions(); + ui.playSelect(); + ui.setModeWithoutClear(Mode.RENAME_POKEMON, { + buttonActions: [ + (nickname: string) => { + ui.playSelect(); + pokemon.nickname = nickname; + pokemon.updateInfo(); + this.clearPartySlots(); + this.populatePartySlots(); + ui.setMode(Mode.PARTY); + }, + () => { + ui.setMode(Mode.PARTY); + } + ] + }, pokemon); + return true; } else if (option === PartyOption.CANCEL) { return this.processInput(Button.CANCEL); } @@ -762,6 +783,7 @@ export default class PartyUiHandler extends MessageUiHandler { } this.options.push(PartyOption.SUMMARY); + this.options.push(PartyOption.RENAME); if (pokemon.pauseEvolutions && pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId)) { this.options.push(PartyOption.UNPAUSE_EVOLUTION); @@ -928,7 +950,7 @@ export default class PartyUiHandler extends MessageUiHandler { } doRelease(slotIndex: integer): void { - this.showText(this.getReleaseMessage(this.scene.getParty()[slotIndex].name), null, () => { + this.showText(this.getReleaseMessage(getPokemonNameWithAffix(this.scene.getParty()[slotIndex])), null, () => { this.clearPartySlots(); this.scene.removePartyMemberModifiers(slotIndex); const releasedPokemon = this.scene.getParty().splice(slotIndex, 1)[0]; @@ -1059,7 +1081,7 @@ class PartySlot extends Phaser.GameObjects.Container { const slotInfoContainer = this.scene.add.container(0, 0); this.add(slotInfoContainer); - let displayName = this.pokemon.name; + let displayName = this.pokemon.getNameToRender(); let nameTextWidth: number; const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.PARTY); diff --git a/src/ui/rename-form-ui-handler.ts b/src/ui/rename-form-ui-handler.ts new file mode 100644 index 00000000000..35127564b60 --- /dev/null +++ b/src/ui/rename-form-ui-handler.ts @@ -0,0 +1,58 @@ +import { FormModalUiHandler } from "./form-modal-ui-handler"; +import { ModalConfig } from "./modal-ui-handler"; +import i18next from "i18next"; +import { PlayerPokemon } from "#app/field/pokemon.js"; + +export default class RenameFormUiHandler extends FormModalUiHandler { + getModalTitle(config?: ModalConfig): string { + return i18next.t("menu:renamePokemon"); + } + + getFields(config?: ModalConfig): string[] { + return [ i18next.t("menu:nickname") ]; + } + + getWidth(config?: ModalConfig): number { + return 160; + } + + getMargin(config?: ModalConfig): [number, number, number, number] { + return [ 0, 0, 48, 0 ]; + } + + getButtonLabels(config?: ModalConfig): string[] { + return [ i18next.t("menu:rename"), i18next.t("menu:cancel") ]; + } + + getReadableErrorMessage(error: string): string { + const colonIndex = error?.indexOf(":"); + if (colonIndex > 0) { + error = error.slice(0, colonIndex); + } + + return super.getReadableErrorMessage(error); + } + + show(args: any[]): boolean { + if (super.show(args)) { + const config = args[0] as ModalConfig; + this.inputs[0].text = (args[1] as PlayerPokemon).getNameToRender(); + + this.submitAction = (_) => { + this.sanitizeInputs(); + // const onFail = () => { + // this.scene.ui.setModeWithoutClear(Mode.RENAME_POKEMON, Object.assign(config)); + // this.scene.ui.playError(); + // }; + // if (!this.inputs[0].text) { + // return onFail(); + // } + const sanitizedName = btoa(unescape(encodeURIComponent(this.inputs[0].text))); + config.buttonActions[0](sanitizedName); + return true; + }; + return true; + } + return false; + } +} diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index e20c7dd31a2..ae1770a45ca 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -302,7 +302,7 @@ export default class SummaryUiHandler extends UiHandler { }); this.pokemon.cry(); - this.nameText.setText(this.pokemon.name); + this.nameText.setText(this.pokemon.getNameToRender()); const isFusion = this.pokemon.isFusion(); diff --git a/src/ui/ui.ts b/src/ui/ui.ts index ce834a83645..ae1bc10a74f 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -46,6 +46,7 @@ import SettingsDisplayUiHandler from "./settings/settings-display-ui-handler"; import SettingsAudioUiHandler from "./settings/settings-audio-ui-handler"; import { PlayerGender } from "#enums/player-gender"; import BgmBar from "#app/ui/bgm-bar"; +import RenameFormUiHandler from "./rename-form-ui-handler"; export enum Mode { MESSAGE, @@ -83,7 +84,8 @@ export enum Mode { SESSION_RELOAD, UNAVAILABLE, OUTDATED, - CHALLENGE_SELECT + CHALLENGE_SELECT, + RENAME_POKEMON } const transitionModes = [ @@ -119,7 +121,8 @@ const noTransitionModes = [ Mode.LOADING, Mode.SESSION_RELOAD, Mode.UNAVAILABLE, - Mode.OUTDATED + Mode.OUTDATED, + Mode.RENAME_POKEMON ]; export default class UI extends Phaser.GameObjects.Container { @@ -180,7 +183,8 @@ export default class UI extends Phaser.GameObjects.Container { new SessionReloadModalUiHandler(scene), new UnavailableModalUiHandler(scene), new OutdatedModalUiHandler(scene), - new GameChallengesUiHandler(scene) + new GameChallengesUiHandler(scene), + new RenameFormUiHandler(scene), ]; }