[Feature] Added pokemon nicknames/renaming (#2570)

* Added basic temp renaming

* Made nickname persistant after reloading

* Localization and cancel button

* Fixed instant rename on active pokemon

* Small bugfix to prevent console errors

* Changed logic to use the new nickname field. Replaced most .name with getNameToRender() for display.

* Changed evolution message. Removed log messagesc

* Added localization keys for other languages

* Removed empty lines

* French translation

Co-authored-by: Lugiad' <adrien.grivel@hotmail.fr>

* Chinese translation

Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com>

* Portuguese (Brazil) translation

Co-authored-by: José Ricardo Fleury Oliveira <josefleury@discente.ufg.br>

* Korean translation

Co-authored-by: Enoch <enoch.jwsong@gmail.com>

* Update menu.ts

* Update menu.ts [Localization(it)]

* Changed most .getNameToRender() instance to getPokemonNameWithAffix()

* Changed wild encounter messages back to just use the name without affix.

* Added localization for the party ui rename selection

* Escaping nickname characters to support all characters

* Better Error handling

* Update src/field/pokemon.ts

Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>

---------

Co-authored-by: Lugiad' <adrien.grivel@hotmail.fr>
Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com>
Co-authored-by: José Ricardo Fleury Oliveira <josefleury@discente.ufg.br>
Co-authored-by: Enoch <enoch.jwsong@gmail.com>
Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>
Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com>
This commit is contained in:
sirzento 2024-07-22 18:46:52 +02:00 committed by GitHub
parent fc722bea7f
commit 01de9b9b58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 247 additions and 88 deletions

View File

@ -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 });
}
}

View File

@ -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)) {

View File

@ -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),
});
}
}

View File

@ -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);

View File

@ -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!`;
}

View File

@ -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(() => {

View File

@ -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();

View File

@ -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;

View File

@ -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(() => {

View File

@ -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;

View File

@ -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?",

View File

@ -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;

View File

@ -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?",

View File

@ -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;

View File

@ -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?",

View File

@ -49,5 +49,9 @@ export const menu: SimpleTranslationEntries = {
"no":"Non",
"disclaimer": "AVERTISSEMENT",
"disclaimerDescription": "Ce jeu nest 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;

View File

@ -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 ?",

View File

@ -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;

View File

@ -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?",

View File

@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = {
"no":"아니오",
"disclaimer": "면책 조항",
"disclaimerDescription": "이 게임은 완전히 개발되지 않았습니다- (세이브 데이터 소실을 포함) 플레이에 지장을 주는 문제가 생길 수 있으며,\n공지 없이 업데이트가 진행 혹은 중지될 수 있습니다.",
"choosePokemon": "포켓몬을 선택하세요.",
"renamePokemon": "포켓몬의 닉네임은?",
"rename": "닉네임 바꾸기",
"nickname": "닉네임",
"errorServerDown": "서버 연결 중 문제가 발생했습니다.\n\n이 창을 종료하지 않고 두면,\n게임은 자동으로 재접속됩니다.",
} as const;

View File

@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = {
"PASS_BATON": "배턴터치한다",
"UNPAUSE_EVOLUTION": "진화 재개",
"REVIVE": "되살린다",
"RENAME": "닉네임 바꾸기",
"choosePokemon": "포켓몬을 선택하세요.",
"doWhatWithThisPokemon": "포켓몬을 어떻게 하겠습니까?",

View File

@ -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;

View File

@ -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?",

View File

@ -54,5 +54,9 @@ export const menu: SimpleTranslationEntries = {
"no": "否",
"disclaimer": "免责声明",
"disclaimerDescription": "这个游戏尚未完成; 可能存在游戏性问题(包括潜在的丢档风险)、\n 不经通知的调整、 未来可能会更新或完成更多内容",
"choosePokemon": "选择一只宝可梦。",
"renamePokemon": "给宝可梦起名",
"rename": "起名",
"nickname": "昵称",
"errorServerDown": "糟糕!访问服务器时发生了错误。\n\n你可以保持页面开启\n游戏会自动重新连接。",
} as const;

View File

@ -16,6 +16,7 @@ export const partyUiHandler: SimpleTranslationEntries = {
"PASS_BATON": "接棒",
"UNPAUSE_EVOLUTION": "解除进化暂停",
"REVIVE": "复活",
"RENAME": "起名",
"choosePokemon": "选择一只宝可梦。",
"doWhatWithThisPokemon": "要对宝可梦做什么?",

View File

@ -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;

View File

@ -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?",

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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),
];
}