From 89dac46dfc2830491c17942174d61e2a74b8ceb8 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Wed, 11 Sep 2024 22:46:26 +0200 Subject: [PATCH 01/16] [Localization] Localization batch - [Not meant to be merged until last minute] (#4127) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com> Co-authored-by: José Ricardo Co-authored-by: Chapybara-jp Co-authored-by: Asdar Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com> Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> Co-authored-by: Enoch Co-authored-by: DanStevensonx <114961842+DanStevensonx@users.noreply.github.com> Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com> Co-authored-by: SangaraSorama <100420976+SangaraSorama@users.noreply.github.com> --- src/locales/de/battler-tags.json | 3 +- src/locales/en/fight-ui-handler.json | 4 +- src/locales/es/battler-tags.json | 3 +- src/locales/es/fight-ui-handler.json | 3 +- src/locales/es/move-trigger.json | 3 +- src/locales/fr/battler-tags.json | 3 +- src/locales/fr/berry.json | 24 +- src/locales/fr/dialogue.json | 10 +- src/locales/fr/fight-ui-handler.json | 5 +- src/locales/fr/modifier-type.json | 2 +- src/locales/fr/move-trigger.json | 7 +- src/locales/fr/pokemon-info.json | 2 +- src/locales/it/battler-tags.json | 3 +- src/locales/it/fight-ui-handler.json | 7 +- src/locales/it/move-trigger.json | 5 +- src/locales/ja/battler-tags.json | 3 +- src/locales/ja/fight-ui-handler.json | 5 +- src/locales/ja/move-trigger.json | 3 +- src/locales/ko/battler-tags.json | 3 +- src/locales/ko/fight-ui-handler.json | 7 +- src/locales/ko/move-trigger.json | 3 +- src/locales/pt_BR/battler-tags.json | 3 +- src/locales/pt_BR/fight-ui-handler.json | 5 +- src/locales/pt_BR/move-trigger.json | 3 +- src/locales/zh_CN/ability.json | 4 +- src/locales/zh_CN/achv.json | 22 +- src/locales/zh_CN/battle.json | 2 +- src/locales/zh_CN/battler-tags.json | 3 +- src/locales/zh_CN/bgm-name.json | 6 +- src/locales/zh_CN/dialogue-double-battle.json | 6 +- src/locales/zh_CN/dialogue-misc.json | 2 +- src/locales/zh_CN/dialogue.json | 34 +- src/locales/zh_CN/fight-ui-handler.json | 7 +- src/locales/zh_CN/modifier-type.json | 10 +- src/locales/zh_CN/move-trigger.json | 9 +- src/locales/zh_CN/party-ui-handler.json | 4 +- src/locales/zh_CN/pokemon-form.json | 4 +- src/locales/zh_CN/splash-messages.json | 4 +- .../zh_CN/starter-select-ui-handler.json | 6 +- src/locales/zh_TW/ability-trigger.json | 55 ++- src/locales/zh_TW/ability.json | 4 +- src/locales/zh_TW/achv.json | 26 +- src/locales/zh_TW/arena-flyout.json | 44 +- src/locales/zh_TW/arena-tag.json | 48 +- src/locales/zh_TW/battle.json | 123 +++-- src/locales/zh_TW/battler-tags.json | 4 +- src/locales/zh_TW/bgm-name.json | 142 +++++- src/locales/zh_TW/challenges.json | 8 +- src/locales/zh_TW/common.json | 6 +- src/locales/zh_TW/dialogue-double-battle.json | 6 +- src/locales/zh_TW/dialogue-misc.json | 2 +- src/locales/zh_TW/dialogue.json | 457 +++++++++++++++++- src/locales/zh_TW/egg.json | 8 +- src/locales/zh_TW/fight-ui-handler.json | 7 +- src/locales/zh_TW/menu-ui-handler.json | 9 +- src/locales/zh_TW/menu.json | 22 +- .../zh_TW/modifier-select-ui-handler.json | 13 +- src/locales/zh_TW/modifier-type.json | 22 +- src/locales/zh_TW/modifier.json | 1 + src/locales/zh_TW/move-trigger.json | 9 +- src/locales/zh_TW/move.json | 4 +- src/locales/zh_TW/party-ui-handler.json | 43 +- src/locales/zh_TW/pokemon-form-battle.json | 8 +- src/locales/zh_TW/pokemon-form.json | 171 ++++++- src/locales/zh_TW/pokemon-info.json | 6 +- src/locales/zh_TW/pokemon-summary.json | 46 +- src/locales/zh_TW/settings.json | 4 +- src/locales/zh_TW/splash-messages.json | 5 +- .../zh_TW/starter-select-ui-handler.json | 9 +- src/locales/zh_TW/status-effect.json | 66 ++- src/locales/zh_TW/trainer-classes.json | 4 +- src/locales/zh_TW/trainer-names.json | 30 +- src/locales/zh_TW/trainer-titles.json | 23 +- src/locales/zh_TW/weather.json | 3 +- 74 files changed, 1419 insertions(+), 261 deletions(-) diff --git a/src/locales/de/battler-tags.json b/src/locales/de/battler-tags.json index e65e1ddfe75..1a04d3d4486 100644 --- a/src/locales/de/battler-tags.json +++ b/src/locales/de/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "{{pokemonNameWithAffix}} wurde durch den Fluch verletzt!", "stockpilingOnAdd": "{{pokemonNameWithAffix}} hortet {{stockpiledCount}}!", "disabledOnAdd": " {{moveName}} von {{pokemonNameWithAffix}} wurde blockiert!", - "disabledLapse": "{{moveName}} von {{pokemonNameWithAffix}} ist nicht länger blockiert!" + "disabledLapse": "{{moveName}} von {{pokemonNameWithAffix}} ist nicht länger blockiert!", + "tarShotOnAdd": "{{pokemonNameWithAffix}} ist nun schwach gegenüber Feuer-Attacken!" } diff --git a/src/locales/en/fight-ui-handler.json b/src/locales/en/fight-ui-handler.json index 1b8bd1f5c71..bd6bec878c8 100644 --- a/src/locales/en/fight-ui-handler.json +++ b/src/locales/en/fight-ui-handler.json @@ -2,7 +2,7 @@ "pp": "PP", "power": "Power", "accuracy": "Accuracy", - "abilityFlyInText": " {{pokemonName}}'s {{passive}}{{abilityName}}", + "abilityFlyInText": " {{pokemonName}}’s\n{{passive}}{{abilityName}}", "passive": "Passive ", "teraHover": "{{type}} Terastallized" -} \ No newline at end of file +} diff --git a/src/locales/es/battler-tags.json b/src/locales/es/battler-tags.json index 891fda53c5d..49efed6e8b4 100644 --- a/src/locales/es/battler-tags.json +++ b/src/locales/es/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "¡{{pokemonNameWithAffix}} es víctima de una maldición!", "stockpilingOnAdd": "¡{{pokemonNameWithAffix}} ha reservado energía por {{stockpiledCount}}ª vez!", "disabledOnAdd": "¡Se ha anulado el movimiento {{moveName}}\nde {{pokemonNameWithAffix}}!", - "disabledLapse": "¡El movimiento {{moveName}} de {{pokemonNameWithAffix}} \n ya no está anulado!" + "disabledLapse": "¡El movimiento {{moveName}} de {{pokemonNameWithAffix}} ya no está anulado!", + "tarShotOnAdd": "¡{{pokemonNameWithAffix}} se ha vuelto débil ante el fuego!" } diff --git a/src/locales/es/fight-ui-handler.json b/src/locales/es/fight-ui-handler.json index dc8140b61fc..fa13f2e0e77 100644 --- a/src/locales/es/fight-ui-handler.json +++ b/src/locales/es/fight-ui-handler.json @@ -3,5 +3,6 @@ "power": "Potencia", "accuracy": "Precisión", "abilityFlyInText": " {{passive}}{{pokemonName}}\n{{abilityName}}", - "passive": "Pasiva de " + "passive": "Pasiva de ", + "teraHover": "Tera-tipo {{type}}" } diff --git a/src/locales/es/move-trigger.json b/src/locales/es/move-trigger.json index f92b7950a07..2322a49056f 100644 --- a/src/locales/es/move-trigger.json +++ b/src/locales/es/move-trigger.json @@ -12,5 +12,6 @@ "stoleItem": "¡{{pokemonName}} robó el objeto\n{{itemName}} de {{targetName}}!", "statEliminated": "¡Los cambios en estadísticas fueron eliminados!", "revivalBlessing": "¡{{pokemonName}} ha revivido!", - "safeguard": "¡{{targetName}} está protegido por Velo Sagrado!" + "safeguard": "¡{{targetName}} está protegido por Velo Sagrado!", + "afterYou": "¡{{pokemonName}} ha decidido aprovechar la oportunidad!" } diff --git a/src/locales/fr/battler-tags.json b/src/locales/fr/battler-tags.json index f523eb7f07d..c4a88bb91aa 100644 --- a/src/locales/fr/battler-tags.json +++ b/src/locales/fr/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "{{pokemonNameWithAffix}} est touché par la malédiction !", "stockpilingOnAdd": "{{pokemonNameWithAffix}} utilise\nla capacité Stockage {{stockpiledCount}} fois !", "disabledOnAdd": "La capacité {{moveName}}\nde {{pokemonNameWithAffix}} est mise sous entrave !", - "disabledLapse": "La capacité {{moveName}}\nde {{pokemonNameWithAffix}} n’est plus sous entrave !" + "disabledLapse": "La capacité {{moveName}}\nde {{pokemonNameWithAffix}} n’est plus sous entrave !", + "tarShotOnAdd": "{{pokemonNameWithAffix}} est maintenant\nvulnérable au feu !" } diff --git a/src/locales/fr/berry.json b/src/locales/fr/berry.json index 833e1d1d8fd..17f28fb8dd0 100644 --- a/src/locales/fr/berry.json +++ b/src/locales/fr/berry.json @@ -1,46 +1,46 @@ { "SITRUS": { "name": "Baie Sitrus", - "effect": "Restaure 25% des PV s’ils sont inférieurs à 50%." + "effect": "Restaure 25% des PV du porteur s’ils sont inférieurs à 50%." }, "LUM": { "name": "Baie Prine", - "effect": "Soigne tout problème de statut permanant et la confusion." + "effect": "Soigne tout problème de statut et la confusion du porteur." }, "ENIGMA": { "name": "Baie Enigma", - "effect": "Restaure 25% des PV si touché par une capacité super efficace." + "effect": "Restaure 25% des PV du porteur s’il est touché par une capacité super efficace." }, "LIECHI": { "name": "Baie Lichii", - "effect": "Augmente l’Attaque si les PV sont inférieurs à 25%." + "effect": "Augmente l’Attaque du porteur si ses PV sont inférieurs à 25%." }, "GANLON": { "name": "Baie Lingan", - "effect": "Augmente la Défense si les PV sont inférieurs à 25%." + "effect": "Augmente la Défense du porteur si ses PV sont inférieurs à 25%." }, "PETAYA": { "name": "Baie Pitaye", - "effect": "Augmente l’Atq. Spé. si les PV sont inférieurs à 25%." + "effect": "Augmente l’Atq. Spé. du porteur si ses PV sont inférieurs à 25%." }, "APICOT": { "name": "Baie Abriko", - "effect": "Augmente la Déf. Spé. si les PV sont inférieurs à 25%." + "effect": "Augmente la Déf. Spé. du porteur si ses PV sont inférieurs à 25%." }, "SALAC": { "name": "Baie Sailak", - "effect": "Augmente la Vitesse si les PV sont inférieurs à 25%." + "effect": "Augmente la Vitesse du porteur si ses PV sont inférieurs à 25%." }, "LANSAT": { "name": "Baie Lansat", - "effect": "Augmente le taux de coups critiques si les PV sont inférieurs à 25%." + "effect": "Augmente le taux de coups critiques du porteur si ses PV sont inférieurs à 25%." }, "STARF": { "name": "Baie Frista", - "effect": "Augmente énormément une statistique au hasard si les PV sont inférieurs à 25%." + "effect": "Augmente énormément une statistique au hasard du porteur si ses PV sont inférieurs à 25%." }, "LEPPA": { "name": "Baie Mepo", - "effect": "Restaure 10 PP à une capacité dès que ses PP tombent à 0." + "effect": "Restaure 10 PP à une capacité du porteur dès que ses PP tombent à 0." } -} \ No newline at end of file +} diff --git a/src/locales/fr/dialogue.json b/src/locales/fr/dialogue.json index dddd0d8e5b7..adc58de0563 100644 --- a/src/locales/fr/dialogue.json +++ b/src/locales/fr/dialogue.json @@ -54,8 +54,8 @@ "3": "J’espère que j’aurai ma revanche un jour.", "4": "C’était super amusant ! Mais ce combat m’a épuisée…", "5": "Tu m’as appris une belle leçon ! T’es vraiment incroyable !", - "6": "Vraiment ? J’ai perdu… ? C’est des choses qui arrivent, ça me déprime mais tu es vraiment très cool.", - "6_female": "Vraiment ? J’ai perdu… ? C’est des choses qui arrivent, ça me déprime mais t’es vraiment très cool.", + "6": "Vraiment ? J’ai perdu… ? Bon, ça arrive, mais c’était cool quand même.", + "6_female": "Vraiment ? J’ai perdu… ? Bon, ça arrive, mais c’était cool quand même.", "7": "J’ai pas besoin de ce genre de souvenirs.\n*Suppression de mémoire en cours…*", "8": "Hé ! Je t’avais dit d’y aller doucement avec moi ! Mais t’es vraiment si cool quand tu te bats sérieusement…", "9": "J’en ai marre des combats Pokémon…\nJe vais chercher d’autres trucs à faire…" @@ -314,8 +314,8 @@ "3": "On est juste des gars et des meufs normaux, on voit un Pokémon on le prend !", "4": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que t’vas jouer frérot.", "4_female": "Pourquoi tu te la joue comme ça ? C'est avec tes dents que t’vas jouer ma reus.", - "5": "Cousin, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu t’incrustes chez nous, ça s’fait pas ! ♪\n$Mais on est sympa, on a un plan pour toi ! ♪", - "5_female": "Cousine, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu t’incrustes chez nous, ça s’fait pas ! ♪\n$Mais on est sympa, on a un plan pour toi ! ♪" + "5": "Cousin, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu t’incrustes chez nous, ça s’fait pas ! ♪\nMais on est sympa, on a un plan pour toi ! ♪", + "5_female": "Cousine, écoute-nous bien ! ♪\nSe taper dessus, ça sert à rien ! ♪\n$Tu t’incrustes chez nous, ça s’fait pas ! ♪\nMais on est sympa, on a un plan pour toi ! ♪" }, "victory": { "1": "Hein ? C’est déjà terminé ?", @@ -687,7 +687,7 @@ }, "rival_6": { "encounter": { - "1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}J’ai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}C’est même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}J’ignore si je serai capable de l’accomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il m’a l’air familier, comme si j’y avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et c’est comme si quelque chose ici me parlait.\n$Comme si c’était tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble semblent si proches ne sont rien de plus qu’un lointain souvenir.\n$@c{neutral_eclosed}D’ailleurs, qui peut dire aujourd’hui qu’ils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu t’arrêtes, ça n’aura jamais de fin et t’es la seule à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que c’est la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens pas à me battre ici et maintenant, tu n’as aucune chance." + "1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}J’ai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}C’est même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}J’ignore si je serai capable de l’accomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il m’a l’air familier, comme si j’y avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et c’est comme si quelque chose ici me parlait.\n$Comme si c’était tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble qui semblent si proches ne sont rien de plus qu’un lointain souvenir.\n$@c{neutral_eclosed}D’ailleurs, qui peut dire aujourd’hui qu’ils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu t’arrêtes, ça n’aura jamais de fin et t’es la seule à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que c’est la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens pas à me battre ici et maintenant, tu n’as aucune chance." }, "victory": { "1": "@c{smile_eclosed}J’ai fait ce que j’avais à faire.\n$Promets-moi juste une chose.\n@c{smile}Après avoir réparé ce monde… Rentre à la maison." diff --git a/src/locales/fr/fight-ui-handler.json b/src/locales/fr/fight-ui-handler.json index e8b41661995..bd4e6b52566 100644 --- a/src/locales/fr/fight-ui-handler.json +++ b/src/locales/fr/fight-ui-handler.json @@ -3,5 +3,6 @@ "power": "Puissance", "accuracy": "Précision", "abilityFlyInText": " {{passive}}{{abilityName}}\nde {{pokemonName}}", - "passive": "Passif " -} \ No newline at end of file + "passive": "Passif ", + "teraHover": "Téracristal {{type}}" +} diff --git a/src/locales/fr/modifier-type.json b/src/locales/fr/modifier-type.json index 78be62cd88f..4f8033b50d7 100644 --- a/src/locales/fr/modifier-type.json +++ b/src/locales/fr/modifier-type.json @@ -202,7 +202,7 @@ "GOLDEN_PUNCH": { "name": "Poing Doré", "description": "La moitié des dégâts infligés sont convertis en argent." }, "COIN_CASE": { "name": "Boite Jetons", "description": "Tous les 10 combats, recevez 10% de votre argent en intérêts." }, - "LOCK_CAPSULE": { "name": "Poké Écrin", "description": "Permet de conserver la rareté des objets si vous relancez les objets proposés." }, + "LOCK_CAPSULE": { "name": "Poké Écrin", "description": "Permet de choisir de bloquer le niveau de rareté lors d’une relance des objets gratuits proposés." }, "GRIP_CLAW": { "name": "Accro Griffe" }, "WIDE_LENS": { "name": "Loupe" }, diff --git a/src/locales/fr/move-trigger.json b/src/locales/fr/move-trigger.json index d9d800c52cc..3704bc90718 100644 --- a/src/locales/fr/move-trigger.json +++ b/src/locales/fr/move-trigger.json @@ -1,9 +1,9 @@ { "hitWithRecoil": "{{pokemonName}} est blessé par le contrecoup !", - "cutHpPowerUpMove": "{{pokemonName}} sacrifie des PV\net augmente la puissance ses capacités !", + "cutHpPowerUpMove": "{{pokemonName}} sacrifie des PV\net augmente la puissance de ses capacités !", "absorbedElectricity": "{{pokemonName}} absorbe de l’électricité !", "switchedStatChanges": "{{pokemonName}} permute\nles changements de stats avec ceux de sa cible !", - "switchedTwoStatChanges": "{{pokemonName}} permute les changements de {{firstStat} et de {{secondStat}} avec ceux de sa cible !", + "switchedTwoStatChanges": "{{pokemonName}} permute les changements de {{firstStat}} et de {{secondStat}} avec ceux de sa cible !", "switchedStat": "{{pokemonName}} et sa cible échangent leur {{stat}} !", "sharedGuard": "{{pokemonName}} additionne sa garde à celle de sa cible et redistribue le tout équitablement !", "sharedPower": "{{pokemonName}} additionne sa force à celle de sa cible et redistribue le tout équitablement !", @@ -66,5 +66,6 @@ "revivalBlessing": "{{pokemonName}} a repris connaissance\net est prêt à se battre de nouveau !", "swapArenaTags": "Les effets affectant chaque côté du terrain\nont été échangés par {{pokemonName}} !", "exposedMove": "{{targetPokemonName}} est identifié\npar {{pokemonName}} !", - "safeguard": "{{targetName}} est protégé\npar la capacité Rune Protect !" + "safeguard": "{{targetName}} est protégé\npar la capacité Rune Protect !", + "afterYou": "{{pokemonName}} accepte\navec joie !" } diff --git a/src/locales/fr/pokemon-info.json b/src/locales/fr/pokemon-info.json index a23b320ea3e..4e53a31035d 100644 --- a/src/locales/fr/pokemon-info.json +++ b/src/locales/fr/pokemon-info.json @@ -17,7 +17,7 @@ "HPStat": "PV" }, "Type": { - "UNKNOWN": "Inconnu", + "UNKNOWN": "???", "NORMAL": "Normal", "FIGHTING": "Combat", "FLYING": "Vol", diff --git a/src/locales/it/battler-tags.json b/src/locales/it/battler-tags.json index e8bda9cfd1e..bd24f380f9e 100644 --- a/src/locales/it/battler-tags.json +++ b/src/locales/it/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "{{pokemonNameWithAffix}} subisce la maledizione!", "stockpilingOnAdd": "{{pokemonNameWithAffix}} ha usato Accumulo per la\n{{stockpiledCount}}ª volta!", "disabledOnAdd": "La mossa {{moveName}} di\n{{pokemonNameWithAffix}} è stata bloccata!", - "disabledLapse": "La mossa {{moveName}} di\n{{pokemonNameWithAffix}} non è più bloccata!" + "disabledLapse": "La mossa {{moveName}} di\n{{pokemonNameWithAffix}} non è più bloccata!", + "tarShotOnAdd": "{{pokemonNameWithAffix}} è diventato vulnerabile\nal tipo Fuoco!" } diff --git a/src/locales/it/fight-ui-handler.json b/src/locales/it/fight-ui-handler.json index 969d8dad370..1c24112a1a7 100644 --- a/src/locales/it/fight-ui-handler.json +++ b/src/locales/it/fight-ui-handler.json @@ -2,6 +2,7 @@ "pp": "PP", "power": "Potenza", "accuracy": "Precisione", - "abilityFlyInText": "{{passive}} {{pokemonName}} {{abilityName}}", - "passive": "Passiva di " -} \ No newline at end of file + "abilityFlyInText": "{{passive}}{{pokemonName}}\n{{abilityName}}", + "passive": "Passiva di ", + "teraHover": "Teracristallizzato {{type}}" +} diff --git a/src/locales/it/move-trigger.json b/src/locales/it/move-trigger.json index 785972b90f9..c8fb390e53f 100644 --- a/src/locales/it/move-trigger.json +++ b/src/locales/it/move-trigger.json @@ -66,5 +66,6 @@ "revivalBlessing": "{{pokemonName}} torna in forze!", "swapArenaTags": "{{pokemonName}} ha invertito gli effetti attivi\nnelle due metà del campo!", "exposedMove": "{{pokemonName}} ha identificato\n{{targetPokemonName}}!", - "safeguard": "Salvaguardia protegge {{targetName}}!" -} \ No newline at end of file + "safeguard": "Salvaguardia protegge {{targetName}}!", + "afterYou": "{{pokemonName}} approfitta della cortesia!" +} diff --git a/src/locales/ja/battler-tags.json b/src/locales/ja/battler-tags.json index 2b6382a3a9f..f8c6d44c0b4 100644 --- a/src/locales/ja/battler-tags.json +++ b/src/locales/ja/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "{{pokemonNameWithAffix}}は のろわれている!", "stockpilingOnAdd": "{{pokemonNameWithAffix}}は {{stockpiledCount}}つ たくわえた!", "disabledOnAdd": "{{pokemonNameWithAffix}}の\n{{moveName}}\nを 封じこめた!", - "disabledLapse": "{{pokemonNameWithAffix}}の\nかなしばりが 解けた!" + "disabledLapse": "{{pokemonNameWithAffix}}の\nかなしばりが 解けた!", + "tarShotOnAdd": "{{pokemonNameWithAffix}}は ほのおに 弱くなった!" } diff --git a/src/locales/ja/fight-ui-handler.json b/src/locales/ja/fight-ui-handler.json index c0c725ccaf3..72cf32f1cd5 100644 --- a/src/locales/ja/fight-ui-handler.json +++ b/src/locales/ja/fight-ui-handler.json @@ -2,6 +2,7 @@ "pp": "PP", "power": "威力", "accuracy": "命中", - "abilityFlyInText": " {{pokemonName}}の\n{{passive}} {{abilityName}}", - "passive": "パッシブ " + "abilityFlyInText": " {{pokemonName}}の\n{{passive}}{{abilityName}}", + "passive": "パッシブ ", + "teraHover": "{{type}}テラスタル" } diff --git a/src/locales/ja/move-trigger.json b/src/locales/ja/move-trigger.json index 7449d8c6e4b..fbefe883836 100644 --- a/src/locales/ja/move-trigger.json +++ b/src/locales/ja/move-trigger.json @@ -65,5 +65,6 @@ "suppressAbilities": "{{pokemonName}}の 特性が 効かなくなった!", "revivalBlessing": "{{pokemonName}}は\n復活して 戦えるようになった!", "swapArenaTags": "{{pokemonName}}は\nお互いの 場の 効果を 入れ替えた!", - "exposedMove": "{{pokemonName}}は {{targetPokemonName}}の\n正体を 見破った!" + "exposedMove": "{{pokemonName}}は {{targetPokemonName}}の\n正体を 見破った!", + "afterYou": "{{pokemonName}}は\nお言葉に 甘えることにした!" } diff --git a/src/locales/ko/battler-tags.json b/src/locales/ko/battler-tags.json index 0993cafa04a..21e548a01a6 100644 --- a/src/locales/ko/battler-tags.json +++ b/src/locales/ko/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "{{pokemonNameWithAffix}}[[는]]\n저주받고 있다!", "stockpilingOnAdd": "{{pokemonNameWithAffix}}[[는]]\n{{stockpiledCount}}개 비축했다!", "disabledOnAdd": "{{pokemonNameWithAffix}}의 {{moveName}}[[는]]\n사용할 수 없다!", - "disabledLapse": "{{pokemonNameWithAffix}}의 {{moveName}}[[는]]\n이제 사용할 수 있다." + "disabledLapse": "{{pokemonNameWithAffix}}의 {{moveName}}[[는]]\n이제 사용할 수 있다.", + "tarShotOnAdd": "{{pokemonNameWithAffix}}[[는]] 불꽃에 약해졌다!" } diff --git a/src/locales/ko/fight-ui-handler.json b/src/locales/ko/fight-ui-handler.json index a5f961095e1..d950e605896 100644 --- a/src/locales/ko/fight-ui-handler.json +++ b/src/locales/ko/fight-ui-handler.json @@ -2,6 +2,7 @@ "pp": "PP", "power": "위력", "accuracy": "명중률", - "abilityFlyInText": " {{pokemonName}}의 {{passive}}{{abilityName}}", - "passive": "패시브 " -} \ No newline at end of file + "abilityFlyInText": " {{pokemonName}}의\n{{passive}}{{abilityName}}", + "passive": "패시브 ", + "teraHover": "{{type}} 테라스탈" +} diff --git a/src/locales/ko/move-trigger.json b/src/locales/ko/move-trigger.json index 2a38bb13b0a..8a3a699d628 100644 --- a/src/locales/ko/move-trigger.json +++ b/src/locales/ko/move-trigger.json @@ -66,5 +66,6 @@ "revivalBlessing": "{{pokemonName}}[[는]]\n정신을 차려 싸울 수 있게 되었다!", "swapArenaTags": "{{pokemonName}}[[는]]\n서로의 필드 효과를 교체했다!", "exposedMove": "{{pokemonName}}[[는]]\n{{targetPokemonName}}의 정체를 꿰뚫어 보았다!", - "safeguard": "{{targetName}}[[는]] 신비의 베일이 지켜 주고 있다!" + "safeguard": "{{targetName}}[[는]] 신비의 베일이 지켜 주고 있다!", + "afterYou": "{{pokemonName}}[[는]]\n배려를 받아들이기로 했다!" } diff --git a/src/locales/pt_BR/battler-tags.json b/src/locales/pt_BR/battler-tags.json index 9c0f4732013..ec6559e12e5 100644 --- a/src/locales/pt_BR/battler-tags.json +++ b/src/locales/pt_BR/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "{{pokemonNameWithAffix}} foi ferido pelo Curse!", "stockpilingOnAdd": "{{pokemonNameWithAffix}} estocou {{stockpiledCount}}!", "disabledOnAdd": "{{moveName}} de {{pokemonNameWithAffix}}\nfoi desabilitado!", - "disabledLapse": "{{moveName}} de {{pokemonNameWithAffix}}\nnão está mais desabilitado." + "disabledLapse": "{{moveName}} de {{pokemonNameWithAffix}}\nnão está mais desabilitado.", + "tarShotOnAdd": "{{pokemonNameWithAffix}} tornou-se mais fraco ao fogo!" } diff --git a/src/locales/pt_BR/fight-ui-handler.json b/src/locales/pt_BR/fight-ui-handler.json index f5c4379126d..8fc41f523eb 100644 --- a/src/locales/pt_BR/fight-ui-handler.json +++ b/src/locales/pt_BR/fight-ui-handler.json @@ -3,5 +3,6 @@ "power": "Poder", "accuracy": "Precisão", "abilityFlyInText": " {{passive}}{{pokemonName}}\n{{abilityName}}", - "passive": "Passiva de " -} \ No newline at end of file + "passive": "Passiva de ", + "teraHover": "Terastalizado {{type}}" +} diff --git a/src/locales/pt_BR/move-trigger.json b/src/locales/pt_BR/move-trigger.json index 9aa13dedad5..4549f83cdf1 100644 --- a/src/locales/pt_BR/move-trigger.json +++ b/src/locales/pt_BR/move-trigger.json @@ -62,5 +62,6 @@ "revivalBlessing": "{{pokemonName}} foi reanimado!", "swapArenaTags": "{{pokemonName}} trocou os efeitos de batalha que afetam cada lado do campo!", "exposedMove": "{{pokemonName}} identificou\n{{targetPokemonName}}!", - "safeguard": "{{targetName}} está protegido por Safeguard!" + "safeguard": "{{targetName}} está protegido por Safeguard!", + "afterYou": "{{pokemonName}} aceitou a gentil oferta!" } diff --git a/src/locales/zh_CN/ability.json b/src/locales/zh_CN/ability.json index 7c70c84f55c..31e3c08161d 100644 --- a/src/locales/zh_CN/ability.json +++ b/src/locales/zh_CN/ability.json @@ -469,7 +469,7 @@ }, "honeyGather": { "name": "采蜜", - "description": "The Pokémon gat\nhers Honey afte\nr a battle. The\n Honey is then \nsold for money." + "description": "战斗结束时,有时候会捡来甜甜蜜。\n甜甜蜜会转换成金钱。" }, "frisk": { "name": "察觉", @@ -1239,4 +1239,4 @@ "name": "毒傀儡", "description": "因桃歹郎的招式而陷入中毒状态的\n对手同时也会陷入混乱状态。" } -} \ No newline at end of file +} diff --git a/src/locales/zh_CN/achv.json b/src/locales/zh_CN/achv.json index 90dfda0e3c1..b93345d876b 100644 --- a/src/locales/zh_CN/achv.json +++ b/src/locales/zh_CN/achv.json @@ -23,7 +23,7 @@ }, "DamageAchv": { - "description": "在单次攻击中造成 {{damageAmount}} 点伤害" + "description": "在单次攻击中造成\n {{damageAmount}} 点伤害" }, "250_DMG": { "name": "重拳出击" @@ -39,7 +39,7 @@ }, "HealAchv": { - "description": "通过技能、能力或携带的道具一次性治疗 {{healAmount}} {{HP}}点" + "description": "通过技能、能力或携带的道具\n一次性治疗 {{healAmount}} {{HP}}点" }, "250_HEAL": { "name": "新手奶妈" @@ -88,11 +88,11 @@ "TRANSFER_MAX_STAT_STAGE": { "name": "团队协作", - "description": "在一项属性强化至最大时用接力棒传递给其他宝可梦" + "description": "在一项属性强化至最大时用\n接力棒传递给其他宝可梦" }, "MAX_FRIENDSHIP": { "name": "亲密无间", - "description": "使一只宝可梦的亲密度达到最大值" + "description": "使一只宝可梦的亲密度\n达到最大值" }, "MEGA_EVOLVE": { "name": "大变身", @@ -112,7 +112,7 @@ }, "SPLICE": { "name": "无限融合", - "description": "使用基因之楔将两只宝可梦融合在一起" + "description": "使用基因之楔将两只宝可梦\n融合在一起" }, "MINI_BLACK_HOLE": { "name": "一大洞的道具", @@ -136,7 +136,7 @@ }, "SHINY_PARTY": { "name": "呕心沥血", - "description": "拥有一支由闪光宝可梦组成的满员队伍" + "description": "拥有一支由闪光宝可梦组成\n的满员队伍" }, "HATCH_MYTHICAL": { "name": "幻兽蛋", @@ -144,7 +144,7 @@ }, "HATCH_SUB_LEGENDARY": { "name": "二级传说蛋", - "description": "从蛋中孵化出一只二级传说宝可梦" + "description": "从蛋中孵化出一只二级传说\n宝可梦" }, "HATCH_LEGENDARY": { "name": "传说蛋", @@ -156,19 +156,19 @@ }, "HIDDEN_ABILITY": { "name": "隐藏实力", - "description": "捕捉一只拥有隐藏特性的宝可梦" + "description": "捕捉一只拥有隐藏特性\n的宝可梦" }, "PERFECT_IVS": { "name": "合格证", - "description": "获得一只拥有完美个体值的宝可梦" + "description": "获得一只拥有完美个体值\n的宝可梦" }, "CLASSIC_VICTORY": { "name": "战无不胜", "description": "在经典模式中通关游戏" }, "UNEVOLVED_CLASSIC_VICTORY": { - "name": "带孩子来上班", - "description": "通关经典模式时队伍中至少有一名未进化的宝可梦" + "name": "带孩上班", + "description": "通关经典模式时队伍中至少有\n一名未进化的宝可梦" }, "MONO_GEN_ONE": { diff --git a/src/locales/zh_CN/battle.json b/src/locales/zh_CN/battle.json index 4197786b7d8..ccf0e560805 100644 --- a/src/locales/zh_CN/battle.json +++ b/src/locales/zh_CN/battle.json @@ -15,7 +15,7 @@ "moneyPickedUp": "捡到了₽{{moneyAmount}}!", "pokemonCaught": "{{pokemonName}}被抓住了!", "addedAsAStarter": "增加了{{pokemonName}}作为\n一个新的基础宝可梦!", - "partyFull": "你的队伍已满员。是否放生其他宝可梦\n为{{pokemonName}}腾出空间?", + "partyFull": "你的队伍已满员。是否放生其他宝可梦\n为{{pokemonName}}腾出空间?", "pokemon": "宝可梦", "sendOutPokemon": "上吧!\n{{pokemonName}}!", "hitResultCriticalHit": "击中了要害!", diff --git a/src/locales/zh_CN/battler-tags.json b/src/locales/zh_CN/battler-tags.json index 792551d1ab1..7a01f5dff23 100644 --- a/src/locales/zh_CN/battler-tags.json +++ b/src/locales/zh_CN/battler-tags.json @@ -69,5 +69,6 @@ "cursedLapse": "{{pokemonNameWithAffix}}\n正受到诅咒!", "stockpilingOnAdd": "{{pokemonNameWithAffix}}蓄力了{{stockpiledCount}}次!", "disabledOnAdd": "封住了{{pokemonNameWithAffix}}的\n{{moveName}}!", - "disabledLapse": "{{pokemonNameWithAffix}}的\n定身法解除了!" + "disabledLapse": "{{pokemonNameWithAffix}}的\n定身法解除了!", + "tarShotOnAdd": "{{pokemonNameWithAffix}}\n变得怕火了!" } diff --git a/src/locales/zh_CN/bgm-name.json b/src/locales/zh_CN/bgm-name.json index d0508a49661..065347e3bb6 100644 --- a/src/locales/zh_CN/bgm-name.json +++ b/src/locales/zh_CN/bgm-name.json @@ -57,7 +57,7 @@ "battle_legendary_dusk_dawn": "究极日月「战斗!日食・月食 奈克洛兹玛」", "battle_legendary_ultra_nec": "究极日月「战斗!究极奈克洛兹玛」", "battle_legendary_zac_zam": "剑盾「战斗!苍响・藏玛然特」", - "battle_legendary_glas_spec": "剑盾「战斗! 雪暴马・灵幽马」", + "battle_legendary_glas_spec": "剑盾「战斗! 雪暴马・灵幽马」", "battle_legendary_calyrex": "剑盾「战斗!蕾冠王」", "battle_legendary_birds_galar": "剑盾「战斗!传说的鸟宝可梦」", "battle_legendary_ruinous": "朱紫「战斗!灾厄宝可梦」", @@ -117,9 +117,9 @@ "plains": "空之探险队「天空顶端(草原)」", "power_plant": "空之探险队「电气平原 深处」", "ruins": "空之探险队「封印岩地 深处」", - "sea": "Andr06 - Marine Mystique", + "sea": "Andr06 - 海洋之秘", "seabed": "Firel - 海底", - "slum": "Andr06 - Sneaky Snom", + "slum": "Andr06 - 狡猾的雪吞虫", "snowy_forest": "空之探险队「天空顶端(雪山)」", "space": "Firel - 太空", "swamp": "空之探险队「封闭之海」", diff --git a/src/locales/zh_CN/dialogue-double-battle.json b/src/locales/zh_CN/dialogue-double-battle.json index 5ab6bf49890..629de3aff3e 100644 --- a/src/locales/zh_CN/dialogue-double-battle.json +++ b/src/locales/zh_CN/dialogue-double-battle.json @@ -9,10 +9,10 @@ }, "red_blue_double": { "encounter": { - "1": "赤红: ...!$青绿: 他人狠话不多。$青绿: 但别被他耍了,\n毕竟他可是个冠军!" + "1": "赤红: ...!$青绿: 他人狠话不多。$青绿: 但别被他耍了,\n毕竟他可是个冠军!" }, "victory": { - "1": "赤红: ...!$青绿: 下次我们一定会赢你!" + "1": "赤红: ...!$青绿: 下次我们一定会赢你!" } }, "tate_liza_double": { @@ -79,4 +79,4 @@ "1": "聂梓:这首歌献给大家!$玛俐:哥哥……" } } -} \ No newline at end of file +} diff --git a/src/locales/zh_CN/dialogue-misc.json b/src/locales/zh_CN/dialogue-misc.json index 07aa336d4f6..b26a3a5f208 100644 --- a/src/locales/zh_CN/dialogue-misc.json +++ b/src/locales/zh_CN/dialogue-misc.json @@ -1,4 +1,4 @@ { "ending": "@c{shock}你回来了?@d{32} 也就是说…@d{96} 你赢了呀!?\n@c{smile_ehalf}我应该早料到了。\n$@c{smile_eclosed}当然…我一直有这种感觉\n@c{smile}一切都结束了,对么? 你打破了循环。\n$@c{smile_ehalf}你也完成了自己的梦想,不是吗?\n你甚至一次都没失败。\n$我是唯一能够记得你所作所为的人\n@c{angry_mopen}我会努力不忘掉哒!\n$@c{smile_wave_wink}开玩笑啦,@d{64} @c{smile}我才不会忘呢。@d{32}\n你的传奇将永远留存于我们心中。\n$@c{smile_wave}不管了,@d{64} 时候不早了@d{96} ,应该吧?\n在这地方还真搞不清楚。\n$一起回家吧。 @c{smile_wave_wink}可能明天,我们再来打一场,为了重温回忆嘛~", - "ending_female": "@c{smile}哦?你赢了?@d{96} @c{smile_eclosed}我应该早猜到了\n你回来了。\n$@c{smile}结束了。@d{64} 你终结了这个循环。\n$@c{serious_smile_fists}你也完成了自己的梦想,不是吗?\n你甚至一次都没失败。\n$@c{neutral}我是唯一能够记得你所作所为的人@d{96}\n我觉得这应该也还行吧?\n$@c{serious_smile_fists}你的传奇将永远留存于我们心中。\n$@c{smile_eclosed}不管了,我真是受够这个地方了,你也一样吗?我们回家吧。\n$@c{serious_smile_fists}可能等我们回家以后,再打一场?\n要是你想的话" + "ending_female": "@c{smile}哦?你赢了?@d{96} @c{smile_eclosed}我应该早猜到了\n你回来了。\n$@c{smile}结束了。@d{64} 你终结了这个循环。\n$@c{serious_smile_fists}你也完成了自己的梦想,不是吗?\n你甚至一次都没失败。\n$@c{neutral}我是唯一能够记得你所作所为的人@d{96}\n我觉得这应该也还行吧?\n$@c{serious_smile_fists}你的传奇将永远留存于我们心中。\n$@c{smile_eclosed}不管了,我真是受够这个地方了,你也一样吗?我们回家吧。\n$@c{serious_smile_fists}可能等我们回家以后,再打一场?\n要是你想的话" } diff --git a/src/locales/zh_CN/dialogue.json b/src/locales/zh_CN/dialogue.json index 5a4615fac54..dd0fa3fb3cc 100644 --- a/src/locales/zh_CN/dialogue.json +++ b/src/locales/zh_CN/dialogue.json @@ -388,7 +388,7 @@ "victory": { "1": "大失误……", "2": "以我现在的实力,无法胜任我的任务……", - "3": "原……谅我,坂木。\n我竟被一名训练师打败了。." + "3": "原……谅我,坂木。\n我竟被一名训练师打败了。" } }, "ariana": { @@ -1230,14 +1230,14 @@ }, "crasher_wake": { "encounter": { - "1": "极限! 极限! 看好了!$极限假面…就此…登场!", - "2": "极限! 极限! 极限假面!", + "1": "极限! 极限! 看好了!$极限假面…就此…登场!", + "2": "极限! 极限! 极限假面!", "3": "我是滔滔巨浪,将你冲走!" }, "victory": { "1": "我真是笑得合不拢嘴啊!$哈哈哈!那真是太有趣了!", "2": "呼哇!结束收尾了!$我该怎么说呢……$我还想再对战!我还想再继续战斗!", - "3": "啊啊啊啊啊!?" + "3": "啊啊啊啊啊!?" }, "defeat": { "1": "耶!就是这样!", @@ -1254,7 +1254,7 @@ "victory": { "1": "明白了……我会礼貌地退场。", "2": "输了就是输了。你确实很强大。", - "3": "…行吧! 嗯, 我输了。" + "3": "…行吧! 嗯, 我输了。" }, "defeat": { "1": "爸爸!我用你珍爱的飞行宝可梦赢了……", @@ -1576,7 +1576,7 @@ }, "clay": { "encounter": { - "1": "咳咳! 让我好等,不是吗,孩子?$好吧,是时候看看你能做到什么了!" + "1": "咳咳! 让我好等,不是吗,孩子?$好吧,是时候看看你能做到什么了!" }, "victory": { "1": "真是的……我先说好,\n我可没有手下留情。" @@ -1802,7 +1802,7 @@ "1": "够野的!你的想法比我的还要毒!" }, "defeat": { - "1": "嘿,拜托!认真点!\n你要加把劲啊!" + "1": "嘿,拜托!认真点!\n你要加把劲啊!" } }, "olivia": { @@ -1884,7 +1884,7 @@ }, "wikstrom": { "encounter": { - "1": "年轻的挑战者,幸会!\n我乃是著名的钢铁之刃,公爵雁铠! $让我们开始战斗吧!预备!" + "1": "年轻的挑战者,幸会!\n我乃是著名的钢铁之刃,公爵雁铠! $让我们开始战斗吧!预备!" }, "victory": { "1": "辉煌!你与你尊贵的\n宝可梦之间的信任居然胜过了我!" @@ -1921,7 +1921,7 @@ "2": "我知道你能走这么远。让我们开始吧。" }, "victory": { - "1": "被你拿下了啊。你太出色了!", + "1": "被你拿下了啊。你太出色了!", "2": "我从没想到会有另一个训练师打败我……$我很惊讶。" }, "defeat": { @@ -2025,13 +2025,13 @@ }, "red": { "encounter": { - "1": "…!" + "1": "…!" }, "victory": { - "1": "…?" + "1": "…?" }, "defeat": { - "1": "…!" + "1": "…!" } }, "jasmine": { @@ -2303,7 +2303,7 @@ }, "grant": { "encounter": { - "1": "我只期待一件事。. $通过超越彼此,\n我们找到通往更高境界的道路。" + "1": "我只期待一件事。$通过超越彼此,\n我们找到通往更高境界的道路。" }, "victory": { "1": "你是一堵我无法逾越的墙!" @@ -2413,7 +2413,7 @@ }, "marnie": { "encounter": { - "1": "事实上,言而总之… \n人家自己也想当冠军呀! $所以别认为我在针对你!" + "1": "事实上,言而总之… \n人家自己也想当冠军呀! $所以别认为我在针对你!" }, "victory": { "1": "好吧,我还是输了……\n但是我看到了很多你和你宝可梦的优点哦" @@ -2468,13 +2468,13 @@ }, "ryme": { "encounter": { - "1": "宝贝, 一起! \n摇滚摇到骨子里!" + "1": "宝贝, 一起! \n摇滚摇到骨子里!" }, "victory": { "1": "你好酷!我佩服!\n我的灵魂为你哭!" }, "defeat": { - "1": "再会, 宝贝!" + "1": "再会, 宝贝!" } }, "grusha": { @@ -2625,7 +2625,7 @@ }, "rival_3_female": { "encounter": { - "1": "@c{smile_wave}好久不见!还没输过,对吧。$@c{angry}我觉得你点烦了。@c{smile_wave_wink}开玩笑啦!$@c{smile_ehalf}但说真的,你现在不想家吗?\n不想…我吗?$我……我的意思是,我们真的很想你。$@c{smile_eclosed}我支持你的一切,包括你的梦想。\n但现实就是你早晚会经历失败。$@c{smile}当你失败的时候,我想像往常一样陪在你身边。$@c{angry_mopen}现在,给你看看我变得多强了吧!" + "1": "@c{smile_wave}好久不见!还没输过,对吧。$@c{angry}我觉得你点烦了。@c{smile_wave_wink}开玩笑啦!$@c{smile_ehalf}但说真的,你现在不想家吗?\n不想…我吗?$我……我的意思是,我们真的很想你。$@c{smile_eclosed}我支持你的一切,包括你的梦想。\n但现实就是你早晚会经历失败。$@c{smile}当你失败的时候,我想像往常一样陪在你身边。$@c{angry_mopen}现在,给你看看我变得多强了吧!" }, "victory": { "1": "@c{shock}都这样了……还是不够吗?$这样下去,你就永远不会回来了……" diff --git a/src/locales/zh_CN/fight-ui-handler.json b/src/locales/zh_CN/fight-ui-handler.json index 8496bf2c1ea..aa8bf4f77c5 100644 --- a/src/locales/zh_CN/fight-ui-handler.json +++ b/src/locales/zh_CN/fight-ui-handler.json @@ -2,6 +2,7 @@ "pp": "PP", "power": "威力", "accuracy": "命中", - "abilityFlyInText": " {{pokemonName}} 的 {{passive}}{{abilityName}}", - "passive": "被动 " -} \ No newline at end of file + "abilityFlyInText": " {{pokemonName}} 的\n{{passive}}{{abilityName}}", + "passive": "被动 ", + "teraHover": "{{type}} 太晶化" +} diff --git a/src/locales/zh_CN/modifier-type.json b/src/locales/zh_CN/modifier-type.json index 26e4c2dc110..981f26a1603 100644 --- a/src/locales/zh_CN/modifier-type.json +++ b/src/locales/zh_CN/modifier-type.json @@ -95,7 +95,7 @@ "description": "招式命中率增加{{accuracyAmount}}(最大100)。" }, "PokemonMultiHitModifierType": { - "description": "攻击以40/25/12.5%的伤害造成2/3/4次伤害" + "description": "攻击以60/75/82.5%的伤害造成2/3/4次伤害。" }, "TmModifierType": { "name": "招式学习器\n{{moveId}} - {{moveName}}", @@ -314,19 +314,19 @@ }, "BERRY_POUCH": { "name": "树果袋", - "description": "使用树果时有30%的几率不会消耗树果。" + "description": "使用树果时增加30%的几率不会消耗树果。" }, "FOCUS_BAND": { "name": "气势头带", - "description": "携带该道具的宝可梦有10%几率在受到攻击\n而将陷入濒死状态时,保留1点HP不陷入濒死状态。" + "description": "携带该道具的宝可梦增加10%几率在受到攻击\n而将陷入濒死状态时,保留1点HP不陷入濒死状态。" }, "QUICK_CLAW": { "name": "先制之爪", - "description": "有10%的几率无视速度优先使出招式\n(先制技能优先)。" + "description": "增加10%的几率无视速度优先使出招式\n(先制技能优先)。" }, "KINGS_ROCK": { "name": "王者之证", - "description": "使用任意原本不会造成畏缩状态的攻击,\n有10%几率使目标陷入畏缩状态。" + "description": "使用任意原本不会造成畏缩状态的攻击,\n增加10%几率使目标陷入畏缩状态。" }, "LEFTOVERS": { "name": "吃剩的东西", diff --git a/src/locales/zh_CN/move-trigger.json b/src/locales/zh_CN/move-trigger.json index 1eb4c397f45..436f1805c4e 100644 --- a/src/locales/zh_CN/move-trigger.json +++ b/src/locales/zh_CN/move-trigger.json @@ -42,12 +42,12 @@ "incineratedItem": "{{pokemonName}}烧没了\n{{targetName}}的{{itemName}}!", "knockedOffItem": "{{pokemonName}}拍落了\n{{targetName}}的{{itemName}}!", "tookMoveAttack": "{{pokemonName}}\n受到了{{moveName}}的攻击!", - "cutOwnHpAndMaximizedStat": "{{pokemonName}}\n削减了体力并释放了全部{{statName}}!", + "cutOwnHpAndMaximizedStat": "{{pokemonName}}\n削减了体力并释放了全部{{statName}}!", "copiedStatChanges": "{{pokemonName}}复制了\n{{targetName}}的能力变化!", "magnitudeMessage": "震级{{magnitude}}!", "tookAimAtTarget": "{{pokemonName}}将目标对准了\n{{targetName}}!", "transformedIntoType": "{{pokemonName}} \n变成了{{typeName}}属性!", - "copiedMove": "{{pokemonName}}\n复制了{{moveName}}!", + "copiedMove": "{{pokemonName}}\n复制了{{moveName}}!", "sketchedMove": "{{pokemonName}}\n对{{moveName}}进行了写生!", "acquiredAbility": "{{pokemonName}}的特性\n变为{{abilityName}}了!", "copiedTargetAbility": "{{pokemonName}}复制了\n{{targetName}}的{{abilityName}}!", @@ -66,5 +66,6 @@ "revivalBlessing": "{{pokemonName}}复活了!", "swapArenaTags": "{{pokemonName}}\n交换了双方的场地效果!", "exposedMove": "{{pokemonName}}识破了\n{{targetPokemonName}}的原型!", - "safeguard": "{{targetName}}\n正受到神秘之幕的保护!" -} \ No newline at end of file + "safeguard": "{{targetName}}\n正受到神秘之幕的保护!", + "afterYou": "{{pokemonName}}\n接受了对手的好意!" +} diff --git a/src/locales/zh_CN/party-ui-handler.json b/src/locales/zh_CN/party-ui-handler.json index db364d29ab2..8dff1ffb75c 100644 --- a/src/locales/zh_CN/party-ui-handler.json +++ b/src/locales/zh_CN/party-ui-handler.json @@ -23,7 +23,7 @@ "tooManyItems": "{{pokemonName}}拥有\n太多这个道具了!", "anyEffect": "即便使用也无效果哦。", "unpausedEvolutions": "{{pokemonName}}的进化停止了。", - "unspliceConfirmation": "真的要把{{fusionName}}\n从{{pokemonName}}身上分离吗? {{fusionName}}会就此消失。", + "unspliceConfirmation": "真的要把{{fusionName}}\n从{{pokemonName}}身上分离吗?{{fusionName}}会就此消失。", "wasReverted": "{{fusionName}}恢复成了{{pokemonName}}。", "releaseConfirmation": "你真要放生{{pokemonName}}吗?", "releaseInBattle": "你无法放生正在战斗中的宝可梦!", @@ -44,4 +44,4 @@ "untilWeMeetAgain": "下次再见了,{{pokemonName}}!", "sayonara": "撒由那拉,{{pokemonName}}!", "smellYaLater": "拜拜了您嘞,{{pokemonName}}!" -} \ No newline at end of file +} diff --git a/src/locales/zh_CN/pokemon-form.json b/src/locales/zh_CN/pokemon-form.json index 09ec54be804..e77f9bdb9fa 100644 --- a/src/locales/zh_CN/pokemon-form.json +++ b/src/locales/zh_CN/pokemon-form.json @@ -1,5 +1,5 @@ { - "pikachuCosplay": "服装", + "pikachuCosplay": "换装", "pikachuCoolCosplay": "摇滚巨星", "pikachuBeautyCosplay": "贵妇", "pikachuCuteCosplay": "流行偶像", @@ -167,4 +167,4 @@ "paldeaTaurosCombat": "斗战种", "paldeaTaurosBlaze": "火炽种", "paldeaTaurosAqua": "水澜种" -} \ No newline at end of file +} diff --git a/src/locales/zh_CN/splash-messages.json b/src/locales/zh_CN/splash-messages.json index f679c43cdb9..4d2d208edfd 100644 --- a/src/locales/zh_CN/splash-messages.json +++ b/src/locales/zh_CN/splash-messages.json @@ -6,7 +6,7 @@ "optionalSaveScumming": "可用SL大法!", "biomes": "35种地区!", "openSource": "开源!", - "playWithSpeed": "请五倍速游玩!", + "playWithSpeed": "请五倍速游玩!", "liveBugTesting": "随时修复BUG!", "heavyInfluence": "深受雨中冒险2影响!", "pokemonRiskAndPokemonRain": "雨中宝可梦冒险!", @@ -33,4 +33,4 @@ "eeveeExpo": "伊布博览会!", "ynoproject": "Yume Nikki 页游项目!", "breedersInSpace": "饲养员也能上太空?" -} \ No newline at end of file +} diff --git a/src/locales/zh_CN/starter-select-ui-handler.json b/src/locales/zh_CN/starter-select-ui-handler.json index d184d5f7c63..4851468ab7c 100644 --- a/src/locales/zh_CN/starter-select-ui-handler.json +++ b/src/locales/zh_CN/starter-select-ui-handler.json @@ -21,8 +21,8 @@ "toggleIVs": "显示个体", "manageMoves": "管理招式", "manageNature": "管理性格", - "addToFavorites": "Add to Favorites", - "removeFromFavorites": "Remove from Favorites", + "addToFavorites": "添加到最爱", + "removeFromFavorites": "移出最爱", "useCandies": "使用糖果", "selectNature": "选择性格", "selectMoveSwapOut": "选择要替换的招式。", @@ -42,4 +42,4 @@ "locked": "未解锁", "disabled": "已禁用", "uncaught": "未捕获" -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/ability-trigger.json b/src/locales/zh_TW/ability-trigger.json index f31fb12bc35..c4b53fa5126 100644 --- a/src/locales/zh_TW/ability-trigger.json +++ b/src/locales/zh_TW/ability-trigger.json @@ -3,11 +3,62 @@ "badDreams": "{{pokemonName}} 被折磨着!", "costar": "{{pokemonName}} 複製了 {{allyName}} 的\n能力變化!", "iceFaceAvoidedDamage": "{{pokemonNameWithAffix}} 因爲 {{abilityName}}\n避免了傷害!", - "trace": "{{pokemonName}} 複製了 {{targetName}} 的\n{{abilityName}}!", - "windPowerCharged": "受 {{moveName}} 的影響, {{pokemonName}} 提升了能力!", + "perishBody": "因爲{{pokemonName}}的{{abilityName}}\n雙方將在3回合後滅亡!", + "poisonHeal": "{{pokemonName}}因{{abilityName}}\n回複了少許HP!", + "trace": "{{pokemonName}}複制了{{targetName}}的\n{{abilityName}}!", + "windPowerCharged": "受{{moveName}}的影響,{{pokemonName}}提升了能力!", + "quickDraw":"因爲速擊效果發動,\n{{pokemonName}}比平常出招更快了!", "disguiseAvoidedDamage": "{{pokemonNameWithAffix}}的畫皮脫落了!", + "blockItemTheft": "{{pokemonNameWithAffix}}的{{abilityName}}\n阻止了對方奪取道具!", + "typeImmunityHeal": "{{pokemonNameWithAffix}}因{{abilityName}}\n回複了少許HP!", + "nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}}因{{abilityName}}\n避免了傷害!", "fullHpResistType": "{{pokemonNameWithAffix}}讓甲殼綻放光輝,扭曲了屬性相剋關係!", + "moveImmunity": "對{{pokemonNameWithAffix}}沒有效果!", + "reverseDrain": "{{pokemonNameWithAffix}}\n吸到了汙泥漿!", + "postDefendTypeChange": "{{pokemonNameWithAffix}}因{{abilityName}}\n變成了{{typeName}}屬性!", + "postDefendContactDamage": "{{pokemonNameWithAffix}}的{{abilityName}}\n使對方受到了傷害!", + "postDefendAbilitySwap": "{{pokemonNameWithAffix}}\n互換了各自的特性!", + "postDefendAbilityGive": "因爲{{pokemonNameWithAffix}}\n對方的特性變成了{{abilityName}}!", + "postDefendMoveDisable": "封住了{{pokemonNameWithAffix}}的\n{{moveName}}!", + "pokemonTypeChange": "{{pokemonNameWithAffix}}\n變成了{{moveType}}屬性!", + "postAttackStealHeldItem": "{{pokemonNameWithAffix}}從{{defenderName}}那裏\n奪取了{{stolenItemType}}!", + "postDefendStealHeldItem": "{{pokemonNameWithAffix}}從{{attackerName}}那裏\n奪取了{{stolenItemType}}!", + "copyFaintedAllyAbility": "繼承了{{pokemonNameWithAffix}}的\n{{abilityName}}!", + "intimidateImmunity": "{{pokemonNameWithAffix}}因{{abilityName}}沒有受到威嚇!", + "postSummonAllyHeal": "{{pokemonNameWithAffix}}喝光了\n{{pokemonName}}泡的茶!", + "postSummonClearAllyStats": "{{pokemonNameWithAffix}}的\n能力變化消失了!", + "postSummonTransform": "{{pokemonNameWithAffix}}\n變身成了{{targetName}}!", + "protectStat": "因{{pokemonNameWithAffix}}的{{abilityName}}\n{{statName}}不會降低!", + "statusEffectImmunityWithName": "{{pokemonNameWithAffix}}因{{abilityName}}\n{{statusEffectName}}沒有效果!", + "statusEffectImmunity": "{{pokemonNameWithAffix}}因{{abilityName}}\n異常狀態沒有效果!", + "battlerTagImmunity": "{{pokemonNameWithAffix}}因{{abilityName}}\n而不會{{battlerTagName}}!", + "forewarn": "{{pokemonNameWithAffix}}讀取了\n{{moveName}}!", + "frisk": "{{pokemonNameWithAffix}}察覺到了\n{{opponentName}}的{{opponentAbilityName}}!", + "postWeatherLapseHeal": "{{pokemonNameWithAffix}}因{{abilityName}}\n回複了少許HP!", + "postWeatherLapseDamage": "{{pokemonNameWithAffix}}\n因{{abilityName}}而受到了傷害!", + "postTurnLootCreateEatenBerry": "{{pokemonNameWithAffix}}\n收獲了{{berryName}}!", + "postTurnHeal": "{{pokemonNameWithAffix}}因{{abilityName}}\n回複了少許HP!", + "fetchBall": "{{pokemonNameWithAffix}}\n撿回了{{pokeballName}}!", + "healFromBerryUse": "{{pokemonNameWithAffix}}因{{abilityName}}\n回複了HP!", + "arenaTrap": "因{{pokemonNameWithAffix}}的{{abilityName}}\n而無法進行替換!", + "postBattleLoot": "{{pokemonNameWithAffix}}撿到了\n{{itemName}}!", + "postFaintContactDamage": "{{pokemonNameWithAffix}}的{{abilityName}}\n使對方受到了傷害!", + "postFaintHpDamage": "{{pokemonNameWithAffix}}的{{abilityName}}\n使對方受到了傷害!", + "postSummonPressure": "從{{pokemonNameWithAffix}}的身上\n感到了一種壓迫感!", "weatherEffectDisappeared": "天氣的影響消失了!", + "postSummonMoldBreaker": "{{pokemonNameWithAffix}}\n打破了常規!", + "postSummonAnticipation": "{{pokemonNameWithAffix}}\n發抖了!", + "postSummonTurboblaze": "{{pokemonNameWithAffix}}\n正在釋放熾焰氣場!", + "postSummonTeravolt": "{{pokemonNameWithAffix}}\n正在釋放濺射氣場!", + "postSummonDarkAura": "{{pokemonNameWithAffix}}\n正在釋放暗黑氣場!", + "postSummonFairyAura": "{{pokemonNameWithAffix}}\n正在釋放妖精氣場!", "postSummonAuraBreak": "{{pokemonNameWithAffix}}壓制了所有氣場!", + "postSummonNeutralizingGas": "周圍充滿了\n{{pokemonNameWithAffix}}的化學變化氣體!", + "postSummonAsOneGlastrier": "{{pokemonNameWithAffix}}\n同時擁有了兩種特性!", + "postSummonAsOneSpectrier": "{{pokemonNameWithAffix}}\n同時擁有了兩種特性!", + "postSummonVesselOfRuin": "{{pokemonNameWithAffix}}的災禍之鼎\n令周圍的寶可夢的{{statName}}減弱了!", + "postSummonSwordOfRuin": "{{pokemonNameWithAffix}}的災禍之劍\n令周圍的寶可夢的{{statName}}減弱了!", + "postSummonTabletsOfRuin": "{{pokemonNameWithAffix}}的災禍之簡\n令周圍的寶可夢的{{statName}}減弱了!", + "postSummonBeadsOfRuin": "{{pokemonNameWithAffix}}的災禍之玉\n令周圍的寶可夢的{{statName}}減弱了!", "preventBerryUse": "{{pokemonNameWithAffix}}因太緊張\n而無法食用樹果!" } diff --git a/src/locales/zh_TW/ability.json b/src/locales/zh_TW/ability.json index ddfe2783794..21206c5362a 100644 --- a/src/locales/zh_TW/ability.json +++ b/src/locales/zh_TW/ability.json @@ -469,7 +469,7 @@ }, "honeyGather": { "name": "採蜜", - "description": "The Pokémon gathers Honey after a battle. The Honey is then sold for money." + "description": "戰鬥結束時,有時候會撿來甜甜蜜。\n甜甜蜜會轉換成金錢。" }, "frisk": { "name": "察覺", @@ -1239,4 +1239,4 @@ "name": "毒傀儡", "description": "因為桃歹郎的招式而陷入中\n毒狀態的對手同時也會陷入\n混亂狀態。" } -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/achv.json b/src/locales/zh_TW/achv.json index 9edce2e368d..804ec0c5089 100644 --- a/src/locales/zh_TW/achv.json +++ b/src/locales/zh_TW/achv.json @@ -21,7 +21,7 @@ "name": "暴發戶" }, "DamageAchv": { - "description": "在單次攻擊中造成 {{damageAmount}} 點傷害" + "description": "在單次攻擊中造成\n {{damageAmount}} 點傷害" }, "250_DMG": { "name": "重拳出擊" @@ -36,7 +36,7 @@ "name": "一拳超人" }, "HealAchv": { - "description": "通過技能、能力或攜帶的道具一次性治療 {{healAmount}} {{HP}}點" + "description": "通過技能、能力或攜帶的道具\n一次性治療 {{healAmount}} {{HP}}點" }, "250_HEAL": { "name": "新手奶媽" @@ -82,11 +82,11 @@ }, "TRANSFER_MAX_STAT_STAGE": { "name": "團隊協作", - "description": "在一項屬性強化至最大時用接力棒傳遞給其他寶可夢" + "description": "在一項屬性強化至最大時用\n接力棒傳遞給其他寶可夢" }, "MAX_FRIENDSHIP": { "name": "親密無間", - "description": "使一隻寶可夢的親密度達到最大值" + "description": "使一隻寶可夢的親密度\n達到最大值" }, "MEGA_EVOLVE": { "name": "大變身", @@ -106,7 +106,7 @@ }, "SPLICE": { "name": "無限融合", - "description": "使用基因之楔將兩隻寶可夢融合在一起" + "description": "使用基因之楔將兩隻寶可夢\n融合在一起" }, "MINI_BLACK_HOLE": { "name": "一大洞的道具", @@ -130,7 +130,7 @@ }, "SHINY_PARTY": { "name": "嘔心瀝血", - "description": "擁有一支由閃光寶可夢組成的滿員隊伍" + "description": "擁有一支由閃光寶可夢組成\n的滿員隊伍" }, "HATCH_MYTHICAL": { "name": "幻獸蛋", @@ -138,7 +138,7 @@ }, "HATCH_SUB_LEGENDARY": { "name": "二級傳說蛋", - "description": "從蛋中孵化出一隻準傳說寶可夢" + "description": "從蛋中孵化出一隻準傳說\n寶可夢" }, "HATCH_LEGENDARY": { "name": "傳說蛋", @@ -150,16 +150,20 @@ }, "HIDDEN_ABILITY": { "name": "隱藏實力", - "description": "捕捉一隻擁有隱藏特性的寶可夢" + "description": "捕捉一隻擁有隱藏特性\n的寶可夢" }, "PERFECT_IVS": { "name": "合格證", - "description": "獲得一隻擁有完美個體值的寶可夢" + "description": "獲得一隻擁有完美個體值\n的寶可夢" }, "CLASSIC_VICTORY": { "name": "戰無不勝", "description": "在經典模式中通關遊戲" }, + "UNEVOLVED_CLASSIC_VICTORY": { + "name": "帶孩上班", + "description": "通關經典模式時隊伍中至少有\n一名未進化的寶可夢" + }, "MONO_GEN_ONE": { "name": "最初的勁敵", "description": "完成僅限第一世代的挑戰." @@ -253,6 +257,10 @@ "MONO_FAIRY": { "name": "林克,醒醒!" }, + "FRESH_START": { + "name": "初次嘗試!", + "description": "完成初次嘗試挑戰" + }, "INVERSE_BATTLE": { "name": "鏡子子鏡", "description": "完成逆轉之戰挑戰\n戰挑戰之轉逆成完" diff --git a/src/locales/zh_TW/arena-flyout.json b/src/locales/zh_TW/arena-flyout.json index 9e26dfeeb6e..e201b683543 100644 --- a/src/locales/zh_TW/arena-flyout.json +++ b/src/locales/zh_TW/arena-flyout.json @@ -1 +1,43 @@ -{} \ No newline at end of file +{ + "activeBattleEffects": "當前戰鬥效果", + "player": "我方", + "neutral": "全局", + "enemy": "敵方", + + "sunny": "大晴天", + "rain": "下雨", + "sandstorm": "沙暴", + "hail": "冰雹", + "snow": "下雪", + "fog": "起霧", + "heavyRain": "大雨", + "harshSun": "大日照", + "strongWinds": "亂流", + + "misty": "薄霧場地", + "electric": "電氣場地", + "grassy": "青草場地", + "psychic": "精神場地", + + "mudSport": "玩泥巴", + "waterSport": "玩水", + "spikes": "撒菱", + "toxicSpikes": "毒菱", + "mist": "白霧", + "futureSight": "預知未來", + "doomDesire": "破滅之願", + "wish": "祈願", + "stealthRock": "隱形岩", + "stickyWeb": "黏黏網", + "trickRoom": "戲法空間", + "gravity": "重力", + "reflect": "反射壁", + "lightScreen": "光牆", + "auroraVeil": "極光幕", + "quickGuard": "快速防守", + "wideGuard": "廣域防守", + "matBlock": "掀榻榻米", + "craftyShield": "戲法防守", + "tailwind": "順風", + "happyHour": "快樂時光" +} diff --git a/src/locales/zh_TW/arena-tag.json b/src/locales/zh_TW/arena-tag.json index 78246d9c44f..a6224f300a3 100644 --- a/src/locales/zh_TW/arena-tag.json +++ b/src/locales/zh_TW/arena-tag.json @@ -1,11 +1,57 @@ { + "yourTeam": "我方隊伍", + "opposingTeam": "敵方隊伍", + "arenaOnRemove": "{{moveName}}的效果消失了!", + "arenaOnRemovePlayer": "{{moveName}}在我方的效果消失了!", + "arenaOnRemoveEnemy": "{{moveName}}在敵方的效果消失了!", + "mistOnAdd": "{{pokemonNameWithAffix}}的一方被\n白霧包圍了!", + "mistApply": "正受到白霧的保護\n能力不會被降低!", + "reflectOnAdd": "反射壁使\n物理抗性提高了!", + "reflectOnAddPlayer": "反射壁使我方的\n物理抗性提高了!", + "reflectOnAddEnemy": "反射壁使敵方的\n物理抗性提高了!", + "lightScreenOnAdd": "光牆使\n特殊抗性提高了!", + "lightScreenOnAddPlayer": "光牆使我方的\n特殊抗性提高了!", + "lightScreenOnAddEnemy": "光牆使敵方的\n特殊抗性提高了!", + "auroraVeilOnAdd": "極光幕使\n物理和特殊抗性提高了!", + "auroraVeilOnAddPlayer": "極光幕使我方的\n物理和特殊抗性提高了!", + "auroraVeilOnAddEnemy": "極光幕使敵方的\n物理和特殊抗性提高了!", + "conditionalProtectOnAdd": "{{moveName}}\n保護了!", + "conditionalProtectOnAddPlayer": "{{moveName}}\n保護了我方!", + "conditionalProtectOnAddEnemy": "{{moveName}}\n保護了敵方!", + "conditionalProtectApply": "{{moveName}}\n保護了{{pokemonNameWithAffix}}!", + "matBlockOnAdd": "{{pokemonNameWithAffix}}正在\n伺機使出掀榻榻米!", "noCritOnAddPlayer": "{{moveName}}保護了你的\n隊伍不被擊中要害!", "noCritOnAddEnemy": "{{moveName}}保護了對方的\n隊伍不被擊中要害!", "noCritOnRemove": "{{pokemonNameWithAffix}}的{{moveName}}\n效果消失了!", + "wishTagOnAdd": "{{pokemonNameWithAffix}}的\n祈願實現了!", + "mudSportOnAdd": "電氣的威力減弱了!", + "mudSportOnRemove": "玩泥巴的效果消失了!", + "waterSportOnAdd": "火焰的威力減弱了!", + "waterSportOnRemove": "玩水的效果消失了!", + "spikesOnAdd": "{{opponentDesc}}腳下\n散落著{{moveName}}!", + "spikesActivateTrap": "{{pokemonNameWithAffix}}\n受到了撒菱的傷害!", + "toxicSpikesOnAdd": "{{opponentDesc}}腳下\n散落著{{moveName}}!", + "toxicSpikesActivateTrapPoison": "{{pokemonNameWithAffix}}\n吸收了{{moveName}}!", + "stealthRockOnAdd": "{{opponentDesc}}周圍\n開始浮現出尖銳的岩石!", + "stealthRockActivateTrap": "尖銳的岩石紮進了\n{{pokemonNameWithAffix}}的體內!", + "stickyWebOnAdd": "對方的腳下\n延伸出了{{moveName}}!", + "stickyWebActivateTrap": "{{pokemonName}}\n被黏黏網粘住了!", + "trickRoomOnAdd": "{{pokemonNameWithAffix}}\n扭曲了時空!", + "trickRoomOnRemove": "扭曲的時空複原了!", + "gravityOnAdd": "重力變強了!", + "gravityOnRemove": "重力複原了!", + "tailwindOnAdd": "從身後\n吹起了順風!", + "tailwindOnAddPlayer": "從我方身後\n吹起了順風!", + "tailwindOnAddEnemy": "從敵方身後\n吹起了順風!", + "tailwindOnRemove": "順風停止了!", + "tailwindOnRemovePlayer": "我方的順風停止了!", + "tailwindOnRemoveEnemy": "敵方的順風停止了!", + "happyHourOnAdd": "大家被歡樂的\n氣氛包圍了!", + "happyHourOnRemove": "氣氛回複到平常了。", "safeguardOnAdd": "整個場地被\n神秘之幕包圍了!", "safeguardOnAddPlayer": "我方被\n神秘之幕包圍了!", "safeguardOnAddEnemy": "對手被\n神秘之幕包圍了!", "safeguardOnRemove": "包圍整個場地的\n神秘之幕消失了!", "safeguardOnRemovePlayer": "包圍我方的\n神秘之幕消失了!", "safeguardOnRemoveEnemy": "包圍對手的\n神秘之幕消失了!" -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/battle.json b/src/locales/zh_TW/battle.json index 0d44688ff4a..66da1b7cace 100644 --- a/src/locales/zh_TW/battle.json +++ b/src/locales/zh_TW/battle.json @@ -1,69 +1,98 @@ { - "bossAppeared": "{{bossName}} 出現了.", + "bossAppeared": "{{bossName}} 出現了。", "trainerAppeared": "{{trainerName}}\n想要和你對戰!", "trainerAppearedDouble": "{{trainerName}}\n想要和你對戰!", - "singleWildAppeared": "一隻野生的 {{pokemonName}} 出現了!", - "multiWildAppeared": "野生的 {{pokemonName1}}\n和 {{pokemonName2}} 出現了!", - "playerComeBack": "回來吧, {{pokemonName}}!", - "trainerComeBack": "{{trainerName}} 收回了 {{pokemonName}}!", - "playerGo": "去吧! {{pokemonName}}!", - "trainerGo": "{{trainerName}} 派出了 {{pokemonName}}!", + "trainerSendOut": "{{trainerName}}派出了\n{{pokemonName}}!", + "singleWildAppeared": "一只野生的{{pokemonName}}出現了!", + "multiWildAppeared": "野生的{{pokemonName1}}\n和{{pokemonName2}}出現了!", + "playerComeBack": "回來吧,{{pokemonName}}!", + "trainerComeBack": "{{trainerName}}收回了{{pokemonName}}!", + "playerGo": "去吧!{{pokemonName}}!", + "trainerGo": "{{trainerName}}派出了\n{{pokemonName}}!", + "trainerSendOut": "{{trainerName}}派出了\n{{pokemonName}}!", + "singleWildAppeared": "一只野生的{{pokemonName}}出現了!", + "multiWildAppeared": "野生的{{pokemonName1}}\n和{{pokemonName2}}出現了!", + "playerComeBack": "回來吧,{{pokemonName}}!", + "trainerComeBack": "{{trainerName}}收回了{{pokemonName}}!", + "playerGo": "去吧!{{pokemonName}}!", + "trainerGo": "{{trainerName}}派出了\n{{pokemonName}}!", "switchQuestion": "要更換\n{{pokemonName}}嗎?", "trainerDefeated": "你擊敗了\n{{trainerName}}!", - "moneyPickedUp": "撿到了 ₽{{moneyAmount}}!", - "pokemonCaught": "{{pokemonName}} 被抓住了!", + "moneyWon": "你贏得了\n₽{{moneyAmount}}!", + "moneyPickedUp": "撿到了₽{{moneyAmount}}!", + "pokemonCaught": "{{pokemonName}}被抓住了!", + "addedAsAStarter": "增加了{{pokemonName}}作爲\n一個新的基礎寶可夢!", + "partyFull": "你的隊伍已滿員。是否放生其他寶可夢\n爲{{pokemonName}}騰出空間?", "pokemon": "寶可夢", - "sendOutPokemon": "上吧! {{pokemonName}}!", + "sendOutPokemon": "上吧!\n{{pokemonName}}!", "hitResultCriticalHit": "擊中了要害!", "hitResultSuperEffective": "效果拔群!", "hitResultNotVeryEffective": "收效甚微…", - "hitResultNoEffect": "對 {{pokemonName}} 沒有效果!", + "hitResultNoEffect": "對{{pokemonName}}沒有效果!", "hitResultImmune": "對于{{pokemonName}},\n完全沒有效果!", - "hitResultOneHitKO": "一擊切殺!", + "hitResultOneHitKO": "一擊必殺!", "attackFailed": "但是失敗了!", "attackMissed": "沒有命中{{pokemonNameWithAffix}}!", - "attackHitsCount": "擊中 {{count}} 次!", - "rewardGain": "You received\n{{modifierName}}!", - "expGain": "{{pokemonName}} 獲得了 {{exp}} 經驗值!", - "levelUp": "{{pokemonName}} 升級到 Lv. {{level}}!", - "learnMove": "{{pokemonName}} 學會了{{moveName}}!", - "learnMovePrompt": "{{pokemonName}} 想要學習 {{moveName}}.", - "learnMoveLimitReached": "但是, {{pokemonName}} 已經學會了\n四個招式.", - "learnMoveReplaceQuestion": "要忘記一個招式並學習 {{moveName}} 嗎?", - "learnMoveStopTeaching": "不再嘗試學習\n{{moveName}}嗎?", - "learnMoveNotLearned": "{{pokemonName}} 沒有學會 {{moveName}}.", + "attackHitsCount": "擊中{{count}}次!", + "rewardGain": "你獲得了\n{{modifierName}}!", + "expGain": "{{pokemonName}}獲得了{{exp}} 點經驗值!", + "levelUp": "{{pokemonName}}升級到Lv.{{level}}!", + "learnMove": "{{pokemonName}}學會了{{moveName}}!", + "learnMovePrompt": "{{pokemonName}}想要學習{{moveName}}。", + "learnMoveLimitReached": "但是,{{pokemonName}}已經學會了\n四個技能", + "learnMoveReplaceQuestion": "要忘記一個技能並學習{{moveName}}嗎?", + "learnMoveStopTeaching": "不再嘗試學習{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}}沒有學會{{moveName}}。", "learnMoveForgetQuestion": "要忘記哪個技能?", - "learnMoveForgetSuccess": "{{pokemonName}} 忘記了 {{moveName}}.", - "countdownPoof": "@d{32}1, @d{15}2, 和@d{15}… @d{15}… @d{15}… @d{15}@s{se/pb_bounce_1}噗!", - "learnMoveAnd": "然後…", - "levelCapUp": "等級上限提升到 {{levelCap}}!", - "moveNotImplemented": "{{moveName}} 未實裝,無法選擇。", + "learnMoveForgetSuccess": "{{pokemonName}}忘記了\n如何使用{{moveName}}。", + "countdownPoof": "@d{32}1, @d{15}2 @d{15}… @d{15}… @d{15}@s{pb_bounce_1}空!", + "learnMoveAnd": "然後……", + "levelCapUp": "等級上限提升到{{levelCap}}!", + "moveNotImplemented": "{{moveName}}尚未實裝,無法選擇。", "moveNoPP": "這個技能的PP用完了", - "moveDisabled": "{{moveName}} 被禁用!", + "moveDisabled": "{{moveName}}被禁用!", "disableInterruptedMove": "{{pokemonNameWithAffix}}的{{moveName}}\n被無效化了!", "noPokeballForce": "一股無形的力量阻止了你使用精靈球。", "noPokeballTrainer": "你不能捕捉其他訓練家的寶可夢!", - "noPokeballMulti": "只能在剩下一隻寶可夢時才能扔出精靈球!", - "noPokeballStrong": "目標寶可夢太強了,無法捕捉!你需要先\n削弱它!", + "noPokeballMulti": "只能在剩下一只寶可夢時才能扔出精靈球!", + "noPokeballStrong": "目標寶可夢太強了,無法捕捉!\n你需要先削弱它!", "noEscapeForce": "一股無形的力量阻止你逃跑。", - "noEscapeTrainer": "你不能從訓練家對戰中逃跑!", - "noEscapePokemon": "{{pokemonName}} 的 {{moveName}} 阻止了你 {{escapeVerb}}!", - "runAwaySuccess": "你成功逃脫了!", - "runAwayCannotEscape": "你無法逃脫!", + "noEscapeTrainer": "你不能從與訓練家的戰鬥中逃跑!", + "noEscapePokemon": "{{pokemonName}}的{{moveName}}\n阻止了你{{escapeVerb}}!", + "runAwaySuccess": "成功逃走了!", + "runAwayCannotEscape": "無法逃走!", "escapeVerbSwitch": "切換", "escapeVerbFlee": "逃跑", - "ppHealBerry": "{{pokemonNameWithAffix}}用{{berryName}}\n回復了{{moveName}}的PP!", - "hpHealBerry": "{{pokemonNameWithAffix}}用{{berryName}}\n回復了體力!", - "notDisabled": "{{moveName}} 不再被禁用!", - "skipItemQuestion": "你要跳過拾取道具嗎?", - "itemStackFull": "{{fullItemName}}持有數已達到上限,\n你獲得了{{itemName}}作爲代替。", + "notDisabled": "{{moveName}}不再被禁用!", + "turnEndHpRestore": "{{pokemonName}}的體力恢複了。", + "hpIsFull": "{{pokemonName}}的體力已滿!", + "skipItemQuestion": "你確定要跳過拾取道具嗎?", + "itemStackFull": "{{fullItemName}}持有數達到上限,\n你獲得了{{itemName}}作爲替代。", "eggHatching": "咦?", - "ivScannerUseQuestion": "對 {{pokemonName}} 使用個體值掃描儀?", - "wildPokemonWithAffix": "野生的 {{pokemonName}}", - "foePokemonWithAffix": "對手 {{pokemonName}}", - "useMove": "{{pokemonNameWithAffix}} 使用了 {{moveName}}!", - "drainMessage": "{{pokemonName}} 吸取了體力!", - "regainHealth": "{{pokemonName}} 回復了體力!", - "fainted": "{{pokemonNameWithAffix}} 倒下了!", - "ppReduced": "降低了 {{targetName}} 的\n{{moveName}} 的PP{{reduction}}點!" + "stealEatBerry": "{{pokemonName}}奪取並吃掉了\n{{targetName}}的{{berryName}}!", + "ppHealBerry": "{{pokemonNameWithAffix}}用{{berryName}}\n回複了{{moveName}}的PP!", + "hpHealBerry": "{{pokemonNameWithAffix}}用{{berryName}}\n回複了體力!", + "ivScannerUseQuestion": "對{{pokemonName}}使用個體值掃描儀?", + "wildPokemonWithAffix": "野生的{{pokemonName}}", + "foePokemonWithAffix": "對手的{{pokemonName}}", + "useMove": "{{pokemonNameWithAffix}}使用了\n{{moveName}}!", + "drainMessage": "{{pokemonName}}\n吸取了體力!", + "regainHealth": "{{pokemonName}}\n回複了體力!", + "fainted": "{{pokemonNameWithAffix}}\n倒下了!", + "statsAnd": "和", + "stats": "能力", + "statRose_other": "{{pokemonNameWithAffix}}的{{stats}}提高了!", + "statSharplyRose_other": "{{pokemonNameWithAffix}}的{{stats}}大幅提高了!", + "statRoseDrastically_other": "{{pokemonNameWithAffix}}的{{stats}}極大幅提高了!", + "statWontGoAnyHigher_other": "{{pokemonNameWithAffix}}的{{stats}}已經無法再提高了!", + "statFell_other": "{{pokemonNameWithAffix}}的{{stats}}降低了!", + "statHarshlyFell_other": "{{pokemonNameWithAffix}}的{{stats}}大幅降低了!", + "statSeverelyFell_other": "{{pokemonNameWithAffix}}的{{stats}}極大幅降低了!", + "statWontGoAnyLower_other": "{{pokemonNameWithAffix}}的{{stats}}已經無法再降低了!", + "transformedIntoType": "{{pokemonName}}變成了\n{{type}}屬性!", + "ppReduced": "降低了{{targetName}}的\n{{moveName}}的PP{{reduction}}點!", + "retryBattle": "你要從對戰開始時重試麽?", + "unlockedSomething": "{{unlockedThing}}\n已解鎖。", + "congratulations": "恭喜!", + "beatModeFirstTime": "{{speciesName}}首次擊敗了{{gameMode}}!\n你獲得了{{newModifier}}!" } diff --git a/src/locales/zh_TW/battler-tags.json b/src/locales/zh_TW/battler-tags.json index b5a2760f7ac..9653db1077a 100644 --- a/src/locales/zh_TW/battler-tags.json +++ b/src/locales/zh_TW/battler-tags.json @@ -67,6 +67,8 @@ "saltCuredLapse": "{{pokemonNameWithAffix}} 受到了{{moveName}}的傷害!", "cursedOnAdd": "{{pokemonNameWithAffix}}削減了自己的體力,並詛咒了{{pokemonName}}!", "cursedLapse": "{{pokemonNameWithAffix}}正受到詛咒!", + "stockpilingOnAdd": "{{pokemonNameWithAffix}}蓄力了{{stockpiledCount}}次!", "disabledOnAdd": "封住了{{pokemonNameWithAffix}}的\n{moveName}}!", - "disabledLapse": "{{pokemonNameWithAffix}}的\n定身法解除了!" + "disabledLapse": "{{pokemonNameWithAffix}}的\n定身法解除了!", + "tarShotOnAdd": "{{pokemonNameWithAffix}}\n變得怕火了!" } diff --git a/src/locales/zh_TW/bgm-name.json b/src/locales/zh_TW/bgm-name.json index 9e26dfeeb6e..e8546750977 100644 --- a/src/locales/zh_TW/bgm-name.json +++ b/src/locales/zh_TW/bgm-name.json @@ -1 +1,141 @@ -{} \ No newline at end of file +{ + "music": "Music: ", + "missing_entries" : "{{name}}", + "battle_kanto_champion": "黑2白2「決戰!關都冠軍」", + "battle_johto_champion": "黑2白2「決戰!城都冠軍」", + "battle_hoenn_champion_g5": "黑2白2「決戰!豐緣冠軍」", + "battle_hoenn_champion_g6": "Ω紅寶石α藍寶石「決戰!豐緣冠軍」", + "battle_sinnoh_champion": "黑2白2「決戰!神奧冠軍」", + "battle_champion_alder": "黑白「決戰!合衆冠軍」", + "battle_champion_iris": "黑2白2「決戰!合衆冠軍」", + "battle_kalos_champion": "XY「決戰!卡洛斯冠軍」", + "battle_alola_champion": "究極日月「頂上決戰!」", + "battle_galar_champion": "劍盾「決戰!伽勒爾冠軍」", + "battle_champion_geeta": "朱紫「決戰!帕底亞首席也慈」", + "battle_champion_nemona": "朱紫「決戰!帕底亞冠軍妮莫」", + "battle_champion_kieran": "朱紫「決戰!藍莓學園冠軍烏栗」", + "battle_hoenn_elite": "Ω紅寶石α藍寶石 「戰鬥!豐緣四天王」", + "battle_unova_elite": "黑白 「戰鬥!合衆四天王」", + "battle_kalos_elite": "XY「戰鬥!卡洛斯四天王」", + "battle_alola_elite": "日月「戰鬥!阿羅拉四天王」", + "battle_galar_elite": "劍盾「聯盟錦標賽」", + "battle_paldea_elite": "朱紫「戰鬥!帕底亞四天王」", + "battle_bb_elite": "朱紫「戰鬥!藍之圓盤四天王」", + "battle_final_encounter": "探險隊DX 「裂空座的領域」", + "battle_final": "黑白「戰鬥!魁奇思」", + "battle_kanto_gym": "黑2白2「戰鬥!關都道館主」", + "battle_johto_gym": "黑2白2「戰鬥!城都道館主」", + "battle_hoenn_gym": "黑2白2「戰鬥!合衆道館主」", + "battle_sinnoh_gym": "黑2白2「戰鬥!神奧道館主」", + "battle_unova_gym": "黑白「戰鬥!合衆道館主」", + "battle_kalos_gym": "XY「戰鬥!卡洛斯道館主」", + "battle_galar_gym": "劍盾「戰鬥!伽勒爾道館主」", + "battle_paldea_gym": "朱紫「戰鬥!帕底亞道館主」", + "battle_legendary_kanto": "XY「戰鬥!傳說寶可夢(關都)」", + "battle_legendary_raikou": "心金魂銀「戰鬥!雷公」", + "battle_legendary_entei": "心金魂銀「戰鬥!炎帝」", + "battle_legendary_suicune": "心金魂銀「戰鬥!水君」", + "battle_legendary_lugia": "心金魂銀「戰鬥!洛奇亞」", + "battle_legendary_ho_oh": "心金魂銀「戰鬥!鳳王」", + "battle_legendary_regis_g5": "黑2白2「戰鬥!傳說中的巨人」", + "battle_legendary_regis_g6": "Ω紅寶石α藍寶石「戰鬥!傳說中的巨人」", + "battle_legendary_gro_kyo": "Ω紅寶石α藍寶石「戰鬥!原始回歸」", + "battle_legendary_rayquaza": "Ω紅寶石α藍寶石「戰鬥!超古代寶可夢」", + "battle_legendary_deoxys": "Ω紅寶石α藍寶石「戰鬥!代歐奇希斯」", + "battle_legendary_lake_trio": "Ω紅寶石α藍寶石「戰鬥!由克希・艾姆利多・亞克諾姆」", + "battle_legendary_sinnoh": "Ω紅寶石α藍寶石「戰鬥!傳說的寶可夢」", + "battle_legendary_dia_pal": "Ω紅寶石α藍寶石「戰鬥!帝牙盧卡・帕路奇亞」", + "battle_legendary_giratina": "Ω紅寶石α藍寶石「戰鬥!騎拉帝納」", + "battle_legendary_arceus": "心金魂銀「阿爾宙斯」", + "battle_legendary_unova": "黑白「戰鬥!傳說的寶可夢」", + "battle_legendary_kyurem": "黑白「戰鬥!酋雷姆」", + "battle_legendary_res_zek": "黑白「戰鬥!萊希拉姆・捷克羅姆」", + "battle_legendary_xern_yvel": "XY「戰鬥!哲爾尼亞斯・伊裴爾塔爾」", + "battle_legendary_tapu": "日月「戰鬥!卡璞」", + "battle_legendary_sol_lun": "日月「戰鬥!露奈雅拉・索爾迦雷歐」", + "battle_legendary_ub": "日月「戰鬥!究極異獸」", + "battle_legendary_dusk_dawn": "究極日月「戰鬥!日食・月食 奈克洛茲瑪」", + "battle_legendary_ultra_nec": "究極日月「戰鬥!究極奈克洛茲瑪」", + "battle_legendary_zac_zam": "劍盾「戰鬥!蒼響・藏瑪然特」", + "battle_legendary_glas_spec": "劍盾「戰鬥! 雪暴馬・靈幽馬」", + "battle_legendary_calyrex": "劍盾「戰鬥!蕾冠王」", + "battle_legendary_birds_galar": "劍盾「戰鬥!傳說的鳥寶可夢」", + "battle_legendary_ruinous": "朱紫「戰鬥!災厄寶可夢」", + "battle_legendary_kor_mir": "朱紫「戰鬥!第零區的寶可夢2」", + "battle_legendary_loyal_three": "朱紫「戰鬥!寶伴」", + "battle_legendary_ogerpon": "朱紫「戰鬥!厄鬼椪」", + "battle_legendary_terapagos": "朱紫「戰鬥!太樂巴戈斯」", + "battle_legendary_pecharunt": "朱紫「戰鬥!桃歹郎」", + "battle_rival": "黑白「戰鬥!黑連・貝爾」", + "battle_rival_2": "黑白「戰鬥!N」", + "battle_rival_3": "黑白「決戰!N」", + "battle_trainer": "黑白「戰鬥!訓練師」", + "battle_wild": "黑白「戰鬥!野生寶可夢」", + "battle_wild_strong": "黑白「戰鬥!強大野生寶可夢」", + "end_summit": "探險隊DX 「天空之柱 頂層」", + "battle_rocket_grunt": "心金魂銀「戰鬥!火箭隊」", + "battle_aqua_magma_grunt": "Ω紅寶石α藍寶石「戰鬥!熔岩隊・海洋隊」", + "battle_galactic_grunt": "晶燦鑽石·明亮珍珠「戰鬥!銀河隊」", + "battle_plasma_grunt": "黑白「戰鬥!等離子團」", + "battle_flare_grunt": "XY「戰鬥!閃焰隊」", + "battle_rocket_boss": "究極日月「戰鬥!坂木」", + "battle_aqua_magma_boss": "Ω紅寶石α藍寶石「戰鬥!水梧桐・赤焰松」", + "battle_galactic_boss": "晶燦鑽石·明亮珍珠「戰鬥!赤日」", + "battle_plasma_boss": "黑2白2「戰鬥!魁奇思」", + "battle_flare_boss": "XY「戰鬥!弗拉達利」", + + "abyss": "空之探險隊「黑暗小丘」", + "badlands": "空之探險隊「枯竭之谷」", + "beach": "空之探險隊「潮濕岩地」", + "cave": "空之探險隊「天空頂端(洞窟)」", + "construction_site": "空之探險隊「幻影石室」", + "desert": "空之探險隊「北方沙漠」", + "dojo": "空之探險隊「嘎啦嘎啦道場」", + "end": "探險隊DX「天空之柱」", + "factory": "空之探險隊「隱藏遺迹」", + "fairy_cave": "空之探險隊「星之洞窟」", + "forest": "空之探險隊「黑暗森林」", + "grass": "空之探險隊「蘋果森林」", + "graveyard": "空之探險隊「神秘森林」", + "ice_cave": "空之探險隊「大冰山」", + "island": "空之探險隊「沿岸岩地」", + "jungle": "Lmz - 叢林", + "laboratory": "Firel - 研究所", + "lake": "空之探險隊「水晶洞窟」", + "meadow": "空之探險隊「天空頂端(森林)」", + "metropolis": "Firel - 城市", + "mountain": "空之探險隊「角山」", + "plains": "空之探險隊「天空頂端(草原)」", + "power_plant": "空之探險隊「電氣平原 深處」", + "ruins": "空之探險隊「封印岩地 深處」", + "sea": "Andr06 - 海洋之秘", + "seabed": "Firel - 海底", + "slum": "Andr06 - 狡猾的雪吞蟲", + "snowy_forest": "空之探險隊「天空頂端(雪山)」", + "space": "Firel - 太空", + "swamp": "空之探險隊「封閉之海」", + "tall_grass": "空之探險隊「濃霧森林」", + "temple": "空之探險隊「守護洞穴」", + "town": "空之探險隊「隨機迷宮3」", + "volcano": "空之探險隊「熱水洞窟」", + "wasteland": "空之探險隊「夢幻高原」", + + "encounter_ace_trainer": "黑白 「視線!精英訓練師」", + "encounter_backpacker": "黑白 「視線!背包客」", + "encounter_clerk": "黑白 「視線!上班族」", + "encounter_cyclist": "黑白 「視線!自行車手」", + "encounter_lass": "黑白 「視線!迷你裙」", + "encounter_parasol_lady": "黑白 「視線!陽傘姐姐」", + "encounter_pokefan": "黑白 「視線!寶可夢愛好者」", + "encounter_psychic": "黑白 「視線!超能力者」", + "encounter_rich": "黑白 「視線!紳士」", + "encounter_rival": "黑白「黑連」", + "encounter_roughneck": "黑白 「視線!光頭」", + "encounter_scientist": "黑白 「視線!科學家」", + "encounter_twins": "黑白 「視線!雙胞胎」", + "encounter_youngster": "黑白 「視線!短褲小子」", + + "heal": "黑白「寶可夢回複」", + "menu": "空之探險隊「歡迎來到寶可夢的世界」", + "title": "空之探險隊「主題曲」" +} diff --git a/src/locales/zh_TW/challenges.json b/src/locales/zh_TW/challenges.json index a1fc6b8f50f..f600cc24a84 100644 --- a/src/locales/zh_TW/challenges.json +++ b/src/locales/zh_TW/challenges.json @@ -20,6 +20,12 @@ "desc": "你只能使用{{type}}\n屬性的寶可夢", "desc_default": "你只能使用所選\n屬性的寶可夢" }, + "freshStart": { + "name": "初次嘗試", + "desc": "你只能使用禦三家,就像是你第一次玩寶可夢肉鴿一樣。", + "value.0": "關閉", + "value.1": "開啓" + }, "inverseBattle": { "name": "逆轉之戰", "shortName": "逆轉之戰", @@ -27,4 +33,4 @@ "value.0": "關閉", "value.1": "開啓" } -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/common.json b/src/locales/zh_TW/common.json index 29ac963ebc3..8b0f91802ee 100644 --- a/src/locales/zh_TW/common.json +++ b/src/locales/zh_TW/common.json @@ -1,8 +1,8 @@ { "start": "開始", - "luckIndicator": "Luck:", - "shinyOnHover": "Shiny", + "luckIndicator": "幸運:", + "shinyOnHover": "閃光", "commonShiny": "常見", "rareShiny": "稀有", "epicShiny": "史詩" -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/dialogue-double-battle.json b/src/locales/zh_TW/dialogue-double-battle.json index 684beac5eaf..612bf3d4490 100644 --- a/src/locales/zh_TW/dialogue-double-battle.json +++ b/src/locales/zh_TW/dialogue-double-battle.json @@ -9,10 +9,10 @@ }, "red_blue_double": { "encounter": { - "1": "赤紅: ...!$青綠:他人狠話不多。$青綠: 他人狠話不多。$青綠: 但別被他耍了,\n畢竟他可是個冠軍!" + "1": "赤紅: ...!$青綠:他人狠話不多。$青綠: 他人狠話不多。$青綠: 但別被他耍了,\n畢竟他可是個冠軍!" }, "victory": { - "1": "赤紅: ...!$青綠: 下次我們一定會贏你!" + "1": "赤紅: ...!$青綠: 下次我們一定會贏你!" } }, "tate_liza_double": { @@ -79,4 +79,4 @@ "1": "聶梓:這首歌獻給大家!$瑪俐:哥哥……" } } -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/dialogue-misc.json b/src/locales/zh_TW/dialogue-misc.json index 408bcac546b..73771e96027 100644 --- a/src/locales/zh_TW/dialogue-misc.json +++ b/src/locales/zh_TW/dialogue-misc.json @@ -1,4 +1,4 @@ { "ending": "@c{shock}你回來了?@d{32} 也就是說…@d{96} 你贏了呀!?\n@c{smile_ehalf}我應該早料到了。\n$@c{smile_eclosed}當然…我一直有這種感覺\n@c{smile}一切都結束了,對麼? 你打破了循環。\n$@c{smile_ehalf}你也完成了自己的夢想,不是嗎?\n你甚至一次都沒失敗。\n$我是唯一能夠記得你所作所為的人\n@c{angry_mopen}我會努力不忘掉哒!\n$@c{smile_wave_wink}開玩笑啦,@d{64} @c{smile}我才不會忘呢。@d{32}\n你的傳奇將永遠留存於我們心中。\n$@c{smile_wave}不管了,@d{64} 時候不早了@d{96} ,應該吧?\n在這地方還真搞不清楚。\n$一起回家吧。 @c{smile_wave_wink}可能明天,我們再來打一場,為了重溫回憶嘛~", - "ending_female": "@c{smile}哦?你贏了?@d{96} @c{smile_eclosed}我應該早猜到了\n你回來了。\n$@c{smile}結束了。@d{64} 你終結了這個循環。\n$@c{serious_smile_fists}你也完成了自己的夢想,不是嗎?\n你甚至一次都沒失敗。\n$@c{neutral}我是唯一能夠記得你所作所為的人@d{96}\n我覺得這應該也還行吧?\n$@c{serious_smile_fists}你的傳奇將永遠留存於我們心中。\n$@c{smile_eclosed}不管了,我真是受夠這個地方了,你也一樣嗎?我們回家吧。\n$@c{serious_smile_fists}可能等我們回家以後,再打一場?\n要是你想的話" + "ending_female": "@c{smile}哦?你贏了?@d{96} @c{smile_eclosed}我應該早猜到了\n你回來了。\n$@c{smile}結束了。@d{64} 你終結了這個循環。\n$@c{serious_smile_fists}你也完成了自己的夢想,不是嗎?\n你甚至一次都沒失敗。\n$@c{neutral}我是唯一能夠記得你所作所為的人@d{96}\n我覺得這應該也還行吧?\n$@c{serious_smile_fists}你的傳奇將永遠留存於我們心中。\n$@c{smile_eclosed}不管了,我真是受夠這個地方了,你也一樣嗎?我們回家吧。\n$@c{serious_smile_fists}可能等我們回家以後,再打一場?\n要是你想的話" } diff --git a/src/locales/zh_TW/dialogue.json b/src/locales/zh_TW/dialogue.json index 4236e239622..99427ac5f14 100644 --- a/src/locales/zh_TW/dialogue.json +++ b/src/locales/zh_TW/dialogue.json @@ -379,6 +379,414 @@ "3": "好像是我暈船了…" } }, + "archer": { + "encounter": { + "1": "在你繼續前進之前,\n讓我看看你要如何和對付火箭隊。", + "2": "我收到報告說你的實力與衆不同,\n就讓我來看看這是否屬實吧。", + "3": "我是阿波羅,火箭對的幹部。\n我不會對組織的敵人手軟。" + }, + "victory": { + "1": "大失誤……", + "2": "以我現在的實力,無法勝任我的任務……", + "3": "原……諒我,坂木。\n我竟被一名訓練師打敗了。." + } + }, + "ariana": { + "encounter": { + "1": "站住!我們可不能放過你!$這會損傷火箭對的名譽,明白嗎?", + "2": "我不知道也不想知道我的所作所爲正確與否…$我只要遵從坂木老大的指令就可以了!", + "3": "你的旅途到此爲止了,我會把你狠狠扳倒!" + }, + "victory": { + "1": "切,你好強,可惡。$如果你加入火箭隊,肯定能成爲幹部。", + "2": "好……好崩潰……", + "3": "嗯啊啊!這不可能!我使出全力還是輸了!" + } + }, + "proton": { + "encounter": { + "1": "你想幹什麽?如果你要妨礙我們的事業,我可不會手下留情。", + "2": "你在這幹什麽?別人總說我是火箭隊裏最殘忍和恐怖的人…$我強烈推薦你別來礙我們的事!", + "3": "我是蘭斯,火箭隊的幹部。就讓來掃除你對我們的阻撓。" + }, + "victory": { + "1": "我的防線崩潰了……", + "2": "你雖然這次贏了,但是這只是讓火箭隊的怒火繼續燃燒!", + "3": "我輸了…但是我不會忘記的。" + } + }, + + "petrel": { + "encounter": { + "1": "哇哈哈哈,我們一直在等你。我?你不知道我是誰?是我,坂木啊。$偉大的坂木大人本人!哇哈哈哈!…啊?我聽起來不像坂木嗎?$我連看起來都不像?怎麽會呢,我可認真的變裝了!", + "2": "我是拉姆達,火箭隊的幹部。我不會允許你幹涉我們的計劃!", + "3": "火箭隊幹部拉姆達來會會這個入侵者!" + }, + "victory": { + "1": "好好好,我會說他在哪的", + "2": "我……我什麽也做不了……坂木,請原諒我……", + "3": "不,我不能慌了神,必須通知其他人…" + } + }, + "tabitha": { + "encounter": { + "1": "呵呵呵!原來你都一路來到這裏了!但你來晚了!", + "2": "呵呵呵……你終于來了?我們小瞧你了,沒不過事! $我比你見過的所有隊員都要厲害,我可不會拖延時間。$我會把你碾碎!", + "3": "我要讓你嘗嘗痛苦的滋味!認命吧!" + }, + "victory": { + "1": "呵呵呵!雖然你打敗了我,但你根本沒機會打敗老大!$如果你現在輸了,你就不用面對那樣嚴厲的鞭笞了!", + "2": "呵呵呵……所以,我也輸了……", + "3": "啊哈!怎麽會這樣?像我這樣的幹部\n竟然輸給了一個隨處可見的訓練師……" + } + }, + "courtney": { + "encounter": { + "1": "那個東西……你所擁有的那個東西……\n那就是……那就是我們熔岩隊所尋找的東西……", + "2": "……那麽……刪除記憶……", + "3": "……哈……分析中……啊哈♪" + }, + "victory": { + "1": "……改變……世界。", + "2": "如預期。出乎意料。目標鎖定…鎖定你……完成。$開始……實驗。材料是你…永遠…啊哈……♪", + "3": "……又來了?出乎意料……我就知道。你……很有趣!……啊哈哈!♪" + } + }, + "shelly": { + "encounter": { + "1": "啊哈哈哈哈!你要插手海洋隊的事?$你要麽是絕對無畏,要麽就是無知,或者兩者兼有!$你太可愛了,太惡心了!我要把你打倒!", + "2": "怎麽回事?這個小鬼頭是誰?", + "3": "冷靜點,耐心點。我很快就會把你擊潰。" + }, + "victory": { + "1": "啊哈哈哈哈!我們意外地被人幹擾了!我們別無選擇。$不得不撤退了,但這會不是你最後一次面對海洋隊!$我們還有其他計劃!別忘了!", + "2": "啊?!我是不是對你太溫柔了?!", + "3": "唉…難道在對戰中你也一刻不停地在變強嗎?$你真是個前途光明的小鬼……\n我和我的寶可夢已經沒有任何力量去戰鬥了……$繼續吧……准備去被水梧桐摧毀吧。" + } + }, + "matt": { + "encounter": { + "1": "嚯!哈哈哈!怎麽,你是不是腦子不正常了?\n看看你,像個幕下力士!", + "2": "“哦吼!你!你真是個有趣的孩子!", + "3": "你在這裏幹什麽?你跟蹤我們了嗎?" + }, + "victory": { + "1": "好吧,在老大有時間對付你之前,我來成爲你的對手!", + "2": "我能感覺到!我感覺到了,沒錯!你身上散發出的力量!$更多!還想要更多!但看起來我們沒時間了……", + "3": "真有趣!我就知道你會讓我盡興的!\n我期待有一天再次面對你!" + } + }, + "mars": { + "encounter": { + "1": "我是夥星,銀河隊的頂級幹部之一。", + "2": "銀河隊對未來的願景堅定不移。\n反對者將被無情地粉碎!", + "3": "“緊張嗎?你是該感到緊張了!" + }, + "victory": { + "1": "這不可能!我怎麽會輸?!", + "2": "你很有本事,我承認。", + "3": "輸了……犯了一個代價高昂的大錯。" + } + }, + "jupiter": { + "encounter": { + "1": "歲星,銀河隊幹部,爲您效勞。", + "2": "抵抗是徒勞的。銀河隊必將獲勝!", + "3": "你在發抖啊……已經害怕了嗎?" + }, + "victory": { + "1": "不會吧……我輸了?!", + "2": "厲害,你膽子真大!", + "3": "輸成這樣……真丟人。" + } + }, + "saturn": { + "encounter": { + "1": "我是鎮星,銀河隊的幹部。", + "2": "我們的使命是絕對的,任何阻礙都將被消滅!", + "3": "我從你的眼中看到的是恐懼嗎?" + }, + "victory": { + "1": "不可能……被你打敗了?!", + "2": "你證明了自己是一個值得尊敬的對手。", + "3": "失敗的苦澀……難以接受……。" + }}, + "zinzolin": { + "encounter": { + "1": "你可能會對等離子隊構成威脅,所以我們現在就消滅你!", + "2": "哦,天哪……我沒想到要在這麽冷的天氣裏戰鬥!", + "3": "能走到今天這一步,你真是個了不起的訓練師。\n但一切到此結束。" + }, + "victory": { + "1": "魁奇思大人……我讓你失望了……", + "2": "好冷,我不僅發抖,還要遭罪。", + "3": "哼。你比我想象的要聰明,但還不夠。" + } + }, + "rood": { + "encounter": { + "1": "你對等離子隊是個威脅。我們現在不能讓你離開這裏!", + "2": "哦,這寒風……我從沒想過我必須在這裏戰鬥!", + "3": "能走到今天這一步,你是一位了不起的訓練師,但這就是你的結局了。" + }, + "victory": { + "1": "魁奇思大人……我的任務失敗了", + "2": "寒風刺骨。我瑟瑟發抖。我痛苦不堪。", + "3": "嗯,你是很有才。但是要打敗等離子隊還不夠……!" + } + }, + "xerosic": { + "encounter": { + "1": "啊哈哈!我很樂意。\n來吧,小訓練師!讓我們看看你有什麽本事!", + "2": "嗯……你比看上去更強大。\n我想知道你體內有多少能量。", + "3": "我一直在等你!我需要對你做一點研究!\n來吧,我們開始吧!" + }, + "victory": { + "1": "啊,你好強大啊……嗯……確實非常強大。", + "2": "叮叮叮!你成功了!\n戰利品歸勝利者!", + "3": "太棒了!太神奇了!\n你的技巧和勇氣都無與倫比!" + } + }, + "bryony": { + "encounter": { + "1": "我是芭拉,能與你一戰是我的榮幸。\n讓我看看你的實力。", + "2": "令人印象深刻……你比你看上去的還要強大。\n讓我們看看你真正的實力。", + "3": "我預料到了你的到來。\n是時候進行一個小實驗了,我們開始吧?" + }, + "victory": { + "1": "你很強大。哦,嗯嗯!確實非常強大", + "2": "叮叮叮!你做得很好。勝利屬于你。", + "3": "太棒了!了不起!你的技巧和勇氣值得稱贊。" + } + }, + "rocket_grunt": { + "encounter": { + "1": "你要有麻煩了!", + "2": "我們要幹大事了!\n閃一邊去,小子!", + "3": "把你的寶可夢交過來,\n不然就嘗嘗火箭隊的厲害!", + "4": "你准備好感受火箭隊真正的恐怖了嗎!", + "5": "喂,小子!俺可是火箭隊滴!" + }, + "victory": { + "1": "好討厭的感覺啊!", + "2": "哎呀!不小心丟掉電梯鑰匙啦!", + "3": "我搞砸了。", + "4": "我的夥計們不會放過你……!", + "5": "你說啥?俺們火箭隊要玩完了?" + } + }, + "magma_grunt": { + "encounter": { + "1": "如果你擋在熔岩隊路上,那就別指望我們手下留情!", + "2": "你最好別妨礙我們的計劃!\n我們會讓世界變得更美好!", + "3": "少礙事!熔岩隊沒時間理你這樣的小孩!", + "4": "你有棉花糖沒?我來給你好好烤烤!", + "5": "我們會利用火山的力量!\n它馬上要…爆發了!懂嗎?嘿嘿嘿……" + }, + "victory": { + "1": "哈?我輸了?!", + "2": "我怎麽會輸!我爲了訓練飯都不吃了!", + "3": "不會吧,不就是一個小孩!", + "4": "唉啊…我得趕快逃回基地…", + "5": "你打敗我了…你覺得老大會扣我工資嗎?" + } + }, + "aqua_grunt": { + "encounter": { + "1": "即使是小孩,如果要和海洋隊作對,也別指望我們手下留情!", + "2": "嚯…你好大的膽子,敢惹我們海洋隊!", + "3": "不僅是我的水系寶可夢,整片大海即將淹沒你!", + "4": "我們海洋隊,是爲了大義!", + "5": "准備好被我的…唉…我寶可夢的海流沖走吧!" + }, + "victory": { + "1": "你在開玩笑吧?", + "2": "害,沒想到這種小屁孩也要管我的閑事!", + "3": "我輸了?看來我得自己遊回基地了。", + "4": "不是吧,怎麽會,老大要生氣了……", + "5": "你打敗了我…老大不會要讓我上跳板吧……" + } + }, + "galactic_grunt": { + "encounter": { + "1": "別惹銀河隊!", + "2": "見識下我們的科技,和我們所設想的未來!", + "3": "以銀河隊之名,我會掃清一切擋路的人!", + "4": "准備輸的一敗塗地吧!", + "5": "希望你做好被宇宙力量碾壓的准備。" + }, + "victory": { + "1": "停機了…", + "2": "從長遠來看,這次的挫折不用在意。", + "3": "小失敗不會影響我們的宏圖偉業!", + "4": "咋回事!?", + "5": "個人記錄:提升對戰水平,優先級,高……" + } + }, + "plasma_grunt": { + "encounter": { + "1": "異端不共戴天!", + "2": "要是我贏了你!就把你的寶可夢放生!", + "3": "要是敢和等離子隊作對,我來好好關照你!", + "4": "等離子隊會從你們這種自私的人手裏解放寶可夢!", + "5": "我們的發型帥的一批,而我們的戰鬥水平呢,\n馬上讓你見識一下。" + }, + "victory": { + "1": "等離子子子子子子!", + "2": "我怎麽會輸……", + "3": "…沒用的家夥!我得去偷個厲害點的寶可夢!", + "4": "偉大的事業總會被人阻撓…", + "5": "爛完了…爛爛爛爛爛!等離子隊爛了!\n說短點就是,等爛子隊!" + } + }, + "flare_grunt": { + "encounter": { + "1": "你的寶可夢無法與閃焰隊的優雅相提並論", + "2": "帶個墨鏡吧,別被我閃瞎狗眼了!", + "3": "閃焰隊將淨化這個不完美的世界!", + "4": "准備面對閃焰隊的美!", + "5": "時尚對我們來說最重要!" + }, + "victory": { + "1": "我的未來看起來並不明亮…", + "2": "這戰鬥比我想的更難搞,我得重頭訓練了。", + "3": "啊啊?我輸了?!", + "4": "就算是在失敗當中,閃焰隊依舊優雅動人!", + "5": "你雖然打敗了我,但是我輸的也這麽潇灑!" + } + }, + "rocket_boss_giovanni_1": { + "encounter": { + "1": "我不得不說,能來到這裏,你的確很不簡單!" + }, + "victory": { + "1": "什麽!這不可能!" + }, + "defeat": { + "1": "記住我的話。無法衡量自己的力量,說明你還是個孩子。" + } + }, + "rocket_boss_giovanni_2": { + "encounter": { + "1": "我的老夥計還需要我…你要擋我的路嗎?" + }, + "victory": { + "1": "這怎麽可能…?\n火箭隊的夢想…就這麽成爲泡影了…" + }, + "defeat": { + "1": "火箭隊會重生,而我會統治世界!" + } + }, + "magma_boss_maxie_1": { + "encounter": { + "1": "我會親手埋葬你,希望你能喜歡!" + }, + "victory": { + "1": "啊!你…很厲害…我落後了…一點…" + }, + "defeat": { + "1": "熔岩隊必勝!" + } + }, + "magma_boss_maxie_2": { + "encounter": { + "1": "你是我實現目標最後的障礙。\n准備好迎接我最強的一擊吧!哈哈哈哈!" + }, + "victory": { + "1": "這…這不…唉" + }, + "defeat": { + "1": "現在…我要把這個星球變成人類的理想國度!" + } + }, + "aqua_boss_archie_1": { + "encounter": { + "1": "我是海洋隊的老大,所以,你的路大概走到頭了。" + }, + "victory": { + "1": "下次再見吧。我會記住你的臉的。" + }, + "defeat": { + "1": "天才!我的隊伍不會再退縮了!" + } + }, + "aqua_boss_archie_2": { + "encounter": { + "1": "我等這一天很久了。\n這就是我的真實力量!" + }, + "victory": { + "1": "果然很強……啊!" + }, + "defeat": { + "1": "我會讓這世界上的一切回歸到最初的純淨狀態!!" + } + }, + "galactic_boss_cyrus_1": { + "encounter": { + "1": "但在這之前,讓我見識見識你那敢向銀河隊叫板的實力吧。" + }, + "victory": { + "1": "有意思,簡直太有意思了。" + }, + "defeat": { + "1": "我要創造我的新世界…" + } + }, + "galactic_boss_cyrus_2": { + "encounter": { + "1": "是啊,我和你還真是有緣呢。\n不過,這段孽緣…就讓我在此斬斷吧!" + }, + "victory": { + "1": "怎麽可能!怎麽可能!怎麽可能!" + }, + "defeat": { + "1": "永別了。" + } + }, + "plasma_boss_ghetsis_1": { + "encounter": { + "1": "無論是誰做了什麽!都無法阻止我!" + }, + "victory": { + "1": "怎麽回事?我可是建立了等離子隊的完美的人啊!\n是要改變世界的完美的統治者!" + }, + "defeat": { + "1": "我是坐擁世界的完美統治者!哇哈哈哈!" + } + }, + "plasma_boss_ghetsis_2": { + "encounter": { + "1": "來吧!讓我看看你徹底絕望時的那張臉!" + }, + "victory": { + "1": "不!我的偉大目標!我要完全支配世界啊!" + }, + "defeat": { + "1": "酋雷姆!融合吧!" + } + }, + "flare_boss_lysandre_1": { + "encounter": { + "1": "你想要阻止我?在對戰中展示給我看吧!" + }, + "victory": { + "1": "看來你的確是想要阻止我。但是,先等一下。" + }, + "defeat": { + "1": "寶可夢…不該存在。" + } + }, + "flare_boss_lysandre_2": { + "encounter": { + "1": "你我的未來…究竟哪個才正確,\n就讓我們來問問各自的寶可夢吧!" + }, + "victory": { + "1": "哇啊啊啊!" + }, + "defeat": { + "1": "沒有遠見的蠢貨會繼續玷汙這個美麗的世界。" + } + }, "brock": { "encounter": { "1": "我對岩石屬性寶可夢的專精會擊敗你!來吧!", @@ -676,14 +1084,14 @@ }, "crasher_wake": { "encounter": { - "1": "極限! 極限! 看好了!$極限假面…就此…登場!", - "2": "極限! 極限! 極限假面!", + "1": "極限! 極限! 看好了!$極限假面…就此…登場!", + "2": "極限! 極限! 極限假面!", "3": "我是滔滔巨浪,將你沖走!" }, "victory": { "1": "我真是笑得合不攏嘴啊!$哈哈哈!那真是太有趣了!", "2": "呼哇!結束收尾了!$我該怎麼說呢……$我還想再對戰!我還想再繼續戰鬥!", - "3": "啊啊啊啊啊!?" + "3": "啊啊啊啊啊!?" }, "defeat": { "1": "耶!就是這樣!", @@ -700,7 +1108,7 @@ "victory": { "1": "明白了……我會禮貌地退場。", "2": "輸了就是輸了。你確實很強大。", - "3": "…行吧! 嗯, 我輸了。" + "3": "…行吧! 嗯, 我輸了。" }, "defeat": { "1": "爸爸!我用你珍愛的飛行寶可夢贏了……", @@ -1022,7 +1430,7 @@ }, "clay": { "encounter": { - "1": "咳咳! 讓我好等,不是嗎,孩子?$好吧,是時候看看你能做到什麼了!" + "1": "咳咳! 讓我好等,不是嗎,孩子?$好吧,是時候看看你能做到什麼了!" }, "victory": { "1": "真是的……我先說好,\n我可沒有手下留情。" @@ -1248,7 +1656,7 @@ "1": "夠野的!你的想法比我的還要毒!" }, "defeat": { - "1": "嘿,拜託!認真點!\n你要加把勁啊!" + "1": "嘿,拜託!認真點!\n你要加把勁啊!" } }, "olivia": { @@ -1330,7 +1738,7 @@ }, "wikstrom": { "encounter": { - "1": "年輕的挑戰者,幸會!\n我乃是著名的鋼鐵之刃,公爵雁鎧! $讓我們開始戰鬥吧!預備!" + "1": "年輕的挑戰者,幸會!\n我乃是著名的鋼鐵之刃,公爵雁鎧! $讓我們開始戰鬥吧!預備!" }, "victory": { "1": "輝煌!你與你尊貴的\n寶可夢之間的信任居然勝過了我!" @@ -1367,7 +1775,7 @@ "2": "我知道你能走這麼遠。讓我們開始吧。" }, "victory": { - "1": "被你拿下了啊。你太出色了!", + "1": "被你拿下了啊。你太出色了!", "2": "我從沒想到會有另一個訓練師打敗我……$我很驚訝。" }, "defeat": { @@ -1471,13 +1879,13 @@ }, "red": { "encounter": { - "1": "…!" + "1": "…!" }, "victory": { - "1": "…?" + "1": "…?" }, "defeat": { - "1": "…!" + "1": "…!" } }, "jasmine": { @@ -1859,7 +2267,7 @@ }, "marnie": { "encounter": { - "1": "事實上,言而總之… \n人家自己也想當冠軍呀! $所以別認為我在針對你!" + "1": "事實上,言而總之… \n人家自己也想當冠軍呀! $所以別認為我在針對你!" }, "victory": { "1": "好吧,我還是輸了……\n但是我看到了很多你和你寶可夢的優點哦" @@ -1914,13 +2322,13 @@ }, "ryme": { "encounter": { - "1": "寶貝, 一起! \n搖滾搖到骨子裡!" + "1": "寶貝, 一起! \n搖滾搖到骨子裡!" }, "victory": { "1": "你好酷!我佩服!\n我的靈魂為你哭!" }, "defeat": { - "1": "再會, 寶貝!" + "1": "再會, 寶貝!" } }, "grusha": { @@ -2012,18 +2420,18 @@ "1": "精彩!簡直就是天下無雙!" }, "defeat": { - "1": "戰鬥結束後,我的心像是吹過了溫和的風…\n$真是厲害!" + "1": "戰鬥結束後,我的心像是吹過了溫和的風…$真是厲害!" } }, "kieran": { "encounter": { - "1": "我的努力讓我越來越強!\n$所以我不會輸。" + "1": "我的努力讓我越來越強!$所以我不會輸。" }, "victory": { - "1": "不可能…\n$真是一場有趣又激動人心的戰鬥啊!" + "1": "不可能…$真是一場有趣又激動人心的戰鬥啊!" }, "defeat": { - "1": "哇塞,好一場戰鬥!\n$你得多練練了。" + "1": "哇塞,好一場戰鬥!$你得多練練了。" } }, "rival": { @@ -2031,7 +2439,7 @@ "1": "@c{smile}嘿,我在找你呢!我知道你急著上路,\n但至少說個再見吧…$@c{smile_eclosed}所以你終於要開始追逐夢想了?\n我幾乎不敢相信。$@c{serious_smile_fists}來都來了,來一場對戰怎麼樣?\n畢竟,我想看看你是不是準備周全了。$@c{serious_mopen_fists}不要手下留情,我想讓你全力以赴!" }, "victory": { - "1": "@c{shock}哇…你徹底擊敗了我。\n你是真初學者嗎?$@c{smile}也許是靠點運氣,但是…\n誰知道,你可能真的能一路走下去。$順便說一下,博士讓我給你這些東西。它們看起來可牛了。$@c{serious_smile_fists}祝你好运!" + "1": "@c{shock}哇…你徹底擊敗了我。\n你是真初學者嗎?$@c{smile}也許是靠點運氣,但是…\n誰知道,你可能真的能一路走下去。$順便說一下,博士讓我給你這些東西。它們看起來可牛了。$@c{serious_smile_fists}祝你好运!$@c{smile}哦!我希望你能喜歡這次的活動!" } }, "rival_female": { @@ -2039,7 +2447,7 @@ "1": "@c{smile_wave}你在這兒啊!我到處找你呢!$@c{angry_mopen}你忘了和你最好的朋友說再見了嗎?$@c{smile_ehalf}你要去追逐夢想了,對吧?\n從今天開始,是不是…$@c{smile}不管怎樣,忘了我的事就原諒你吧,\n但有個條件。@c{smile_wave_wink}你必須和我對戰!$@c{angry_mopen}全力以赴!\n你也不想讓你的冒險在開始之前就結束了,對吧?" }, "victory": { - "1": "@c{shock}你剛開始就已經這麼強了?!@d{96}$@c{angry}你是不是開了?$@c{smile_wave_wink}只是開個玩笑啦!@d{64} @c{smile_eclosed}我輸地心服口服了…\n我感覺你出去挺有天賦的。$@c{smile}順便說一下,博士想讓我給你一些東西。\n希望它們能幫上忙!$@c{smile_wave}像往常一樣盡力而為!\n我相信你!" + "1": "@c{shock}你剛開始就已經這麼強了?!@d{96}$@c{angry}你是不是開了?$@c{smile_wave_wink}只是開個玩笑啦!@d{64} @c{smile_eclosed}我輸地心服口服了…\n我感覺你出去挺有天賦的。$@c{smile}順便說一下,博士想讓我給你一些東西。\n希望它們能幫上忙!$@c{smile_wave}像往常一樣盡力而為!\n我相信你!$@c{smile}哦!我希望你能喜歡這次的活動!" } }, "rival_2": { @@ -2047,7 +2455,7 @@ "1": "@c{smile}嘿,你也在這裡嗎?$@c{smile_eclosed}一路過關斬將,是吧?$@c{serious_mopen_fists}我知道看起來好像我尾隨著你來到這裡,\n怎麼可能啦。$@c{serious_smile_fists}說真的,自從你在老家打敗我後,\n我就一直很渴望再比一場。$我自己也進行了很多訓練,\n所以這次我肯定會好好打一場。$@c{serious_mopen_fists}不要手下留情,就像以前一樣!$讓我們開始吧!" }, "victory": { - "1": "@c{neutral_eclosed}哦。我過於自信了。$@c{smile}不過沒關係。我猜到可能會這樣。$@c{serious_mopen_fists}這只意味著我下次需要更努力!$$@c{smile}呃,不是特意幫你,我正好有多餘的這個,\n我覺得你可能想要。$$@c{serious_smile_fists}不過這次之後別指望再有了!$我不能一直給我的對手優勢。$@c{smile}反正,保重!" + "1": "@c{neutral_eclosed}哦。我過於自信了。$@c{smile}不過沒關係。我猜到可能會這樣。$@c{serious_mopen_fists}這只意味著我下次需要更努力!$$@c{smile}呃,不是特意幫你,我正好有多餘的這個,\n我覺得你可能想要。$$@c{serious_smile_fists}不過這次之後別指望再有了!$我不能一直給我的對手優勢。$@c{smile}反正,保重, 要享受活動哦!" } }, "rival_2_female": { @@ -2055,7 +2463,7 @@ "1": "@c{smile_wave}哦,真巧,在這裡遇見你。\n看來你還沒輸過嘛。@c{angry_mopen}哈……好傢伙!$@c{angry_mopen}我知道你在想什麼,\n不,我才不會跟蹤你什麼呢。 @c{smile_eclosed}我只是碰巧在附近。$@c{smile_ehalf}我為你感到高興,但我只想讓你知道\n有時輸了是可以接受的。$@c{smile}我們從錯誤中學到的東西\n往往比我們一直成功時學到的還要多。$@c{angry_mopen}無論如何,我為了我們的複賽已經努力訓練了\n所以你最好全力以赴!" }, "victory": { - "1": "@c{neutral}我……沒打算會輸來著……$@c{smile}嗷……好吧。看來我要再更加努力訓練了!$@c{smile_wave}我還給你帶了個這個$@c{smile_wave_wink}不用謝我哦~.$@c{angry_mopen}不過,這是最後一個啦!\n 你可別想再從我這賺小便宜了~$@c{smile_wave}要保重哦!" + "1": "@c{neutral}我……沒打算會輸來著……$@c{smile}嗷……好吧。看來我要再更加努力訓練了!$@c{smile_wave}我還給你帶了個這個$@c{smile_wave_wink}不用謝我哦~.$@c{angry_mopen}不過,這是最後一個啦!\n 你可別想再從我這賺小便宜了~$@c{smile_wave}要保重哦,要享受活動哦!" }, "defeat": { "1": "輸了有時候也不要緊的…" @@ -2071,7 +2479,7 @@ }, "rival_3_female": { "encounter": { - "1": "@c{smile_wave}好久不見!還沒輸過,對吧。$@c{angry}我覺得你點煩了。@c{smile_wave_wink}開玩笑啦!$@c{smile_ehalf}但說真的,你現在不想家嗎?\n 不想…我嗎?$我……我的意思是,我們真的很想你。$@c{smile_eclosed}我支持你的一切,包括你的夢想。\n但現實就是你早晚會經歷失敗。$@c{smile}當你失敗的時候,我想像往常一樣陪在你身邊。$@c{angry_mopen}現在,給你看看我變得多強了吧!" + "1": "@c{smile_wave}好久不見!還沒輸過,對吧。$@c{angry}我覺得你點煩了。@c{smile_wave_wink}開玩笑啦!$@c{smile_ehalf}但說真的,你現在不想家嗎?\n 不想…我嗎?$我……我的意思是,我們真的很想你。$@c{smile_eclosed}我支持你的一切,包括你的夢想。\n但現實就是你早晚會經歷失敗。$@c{smile}當你失敗的時候,我想像往常一樣陪在你身邊。$@c{angry_mopen}現在,給你看看我變得多強了吧!" }, "victory": { "1": "@c{shock}都這樣了……還是不夠嗎?$這樣下去,你就永遠不會回來了……" @@ -2113,6 +2521,7 @@ }, "victory": { "1": "@c{neutral}…" + }, "defeat": { "1": "$@c{smile_ehalf}…" @@ -2134,4 +2543,4 @@ "1": "@c{smile_ehalf}我……\n我想我完成了我的使命……$@c{smile_eclosed}答應我……在你拯救世界之後\n……要……平安到家。$@c{smile_ehalf}……謝謝你。" } } -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/egg.json b/src/locales/zh_TW/egg.json index 28e5e1b9bda..0178848a0d5 100644 --- a/src/locales/zh_TW/egg.json +++ b/src/locales/zh_TW/egg.json @@ -20,7 +20,7 @@ "hatchFromTheEgg": "{{pokemonName}} 從蛋中孵化了!", "eggMoveUnlock": "蛋招式已解鎖: {{moveName}}", "rareEggMoveUnlock": "稀有蛋招式已解鎖: {{moveName}}", - "moveUPGacha": "蛋招式UP!", - "shinyUPGacha": "闪光UP!", - "legendaryUPGacha": "UP!" -} \ No newline at end of file + "moveUPGacha": "蛋招式UP!", + "shinyUPGacha": "闪光UP!", + "legendaryUPGacha": "UP!" +} diff --git a/src/locales/zh_TW/fight-ui-handler.json b/src/locales/zh_TW/fight-ui-handler.json index 3cf1868196a..dda3e443b36 100644 --- a/src/locales/zh_TW/fight-ui-handler.json +++ b/src/locales/zh_TW/fight-ui-handler.json @@ -2,6 +2,7 @@ "pp": "PP", "power": "威力", "accuracy": "命中率", - "abilityFlyInText": " {{pokemonName}} 的 {{passive}}{{abilityName}}", - "passive": "被動能力 " -} \ No newline at end of file + "abilityFlyInText": " {{pokemonName}} 的\n{{passive}}{{abilityName}}", + "passive": "被動能力 ", + "teraHover": "{{type}} 太晶化" +} diff --git a/src/locales/zh_TW/menu-ui-handler.json b/src/locales/zh_TW/menu-ui-handler.json index 33e6b44d73d..cbb5b604d33 100644 --- a/src/locales/zh_TW/menu-ui-handler.json +++ b/src/locales/zh_TW/menu-ui-handler.json @@ -19,6 +19,11 @@ "importData": "導入數據", "exportData": "導出數據", "consentPreferences": "同意偏好", + "linkDiscord": "關聯Discord", + "unlinkDiscord": "解除關聯Discord", + "linkGoogle": "關聯Google", + "unlinkGoogle": "解除關聯Google", "cancel": "取消", - "losingProgressionWarning": "你將失去自戰鬥開始以來的所有進度。是否\n繼續?" -} \ No newline at end of file + "losingProgressionWarning": "你將失去自戰鬥開始以來的所有進度。是否\n繼續?", + "noEggs": "當前沒有任何蛋\n正在孵化中!" +} diff --git a/src/locales/zh_TW/menu.json b/src/locales/zh_TW/menu.json index b56a39bbda2..fee9b1be85d 100644 --- a/src/locales/zh_TW/menu.json +++ b/src/locales/zh_TW/menu.json @@ -6,11 +6,11 @@ "newGame": "新遊戲", "settings": "設定", "selectGameMode": "選擇遊戲模式", - "logInOrCreateAccount": "登入或註冊即可開始遊戲,無需郵箱!", + "logInOrCreateAccount": "登入或註冊即可開始遊戲,無需郵箱!", "username": "用戶名", "password": "密碼", "login": "登入", - "orUse": "Or use", + "orUse": "或使用", "register": "注冊", "emptyUsername": "用戶名不能為空", "invalidLoginUsername": "提供的用戶名無效", @@ -27,10 +27,10 @@ "failedToLoadSaveData": "讀取存檔數據失敗。請重新加載頁面。如果\n問題仍然存在,請聯繫管理員。", "sessionSuccess": "工作階段加載成功.", "failedToLoadSession": "無法加載您的工作階段數據。它可能已損壞。", - "boyOrGirl": "你是男孩還是女孩?", - "evolving": "甚麼?\n{{pokemonName}} 要進化了!", + "boyOrGirl": "你是男孩還是女孩?", + "evolving": "甚麼?\n{{pokemonName}} 要進化了!", "stoppedEvolving": "{{pokemonName}} 停止了進化。", - "pauseEvolutionsQuestion": "你確定要停止 {{pokemonName}} 的進化嗎?\n你可以在隊伍畫面中重新啟用進化。", + "pauseEvolutionsQuestion": "你確定要停止 {{pokemonName}} 的進化嗎?\n你可以在隊伍畫面中重新啟用進化。", "evolutionsPaused": "{{pokemonName}}的進化已暫停。", "evolutionDone": "恭喜!\n你的 {{pokemonName}} 進化成了 {{evolvedPokemonName}}!", "dailyRankings": "每日排名", @@ -38,9 +38,17 @@ "noRankings": "無排名", "positionIcon": "#", "loading": "加載中…", + "loadingAsset": "加載資源: {{assetName}}", "playersOnline": "在線玩家", "yes": "是", "no": "否", - "noSaves": "你沒有任何記錄檔!", - "tooManySaves": "你的記錄檔太多了!" + "disclaimer": "免責聲明", + "disclaimerDescription": "這個遊戲尚未完成; 可能存在遊戲性問題(包括潛在的丟檔風險)、\n 不經通知的調整、 未來可能會更新或完成更多內容", + "choosePokemon": "選擇一只寶可夢。", + "renamePokemon": "給寶可夢起名", + "rename": "起名", + "nickname": "昵稱", + "errorServerDown": "糟糕!訪問服務器時發生了錯誤。\n\n你可以保持頁面開啓,\n遊戲會自動重新連接。", + "noSaves": "你沒有任何記錄檔!", + "tooManySaves": "你的記錄檔太多了!" } diff --git a/src/locales/zh_TW/modifier-select-ui-handler.json b/src/locales/zh_TW/modifier-select-ui-handler.json index 9e26dfeeb6e..84ebbbfef6a 100644 --- a/src/locales/zh_TW/modifier-select-ui-handler.json +++ b/src/locales/zh_TW/modifier-select-ui-handler.json @@ -1 +1,12 @@ -{} \ No newline at end of file +{ + "transfer": "交換道具", + "reroll": "刷新商店", + "lockRarities": "鎖定稀有度", + "checkTeam": "查看隊伍", + "transferDesc": "將寶可夢攜帶的道具交換給其他寶可夢", + "rerollDesc": "花錢刷新道具", + "lockRaritiesDesc": "在刷新時鎖定道具稀有度(影響刷新費用)", + "checkTeamDesc": "檢查隊伍或使用形態改變道具", + "rerollCost": "₽{{formattedMoney}}", + "itemCost": "₽{{formattedMoney}}" +} diff --git a/src/locales/zh_TW/modifier-type.json b/src/locales/zh_TW/modifier-type.json index ec066277cda..6ff593ddba7 100644 --- a/src/locales/zh_TW/modifier-type.json +++ b/src/locales/zh_TW/modifier-type.json @@ -60,10 +60,10 @@ "description": "一隻寶可夢的{{moveType}}系招式威力提升20%。" }, "PokemonLevelIncrementModifierType": { - "description": "Increases a Pokémon's level by {{levels}}." + "description": "使一只寶可夢的等級提升{{levels}}級。" }, "AllPokemonLevelIncrementModifierType": { - "description": "Increases all party members' level by {{levels}}." + "description": "使一只寶可夢的等級提升{{levels}}級。" }, "BaseStatBoosterModifierType": { "description": "增加持有者的{{stat}}10%,個體值越高堆疊\n上限越高。" @@ -95,15 +95,15 @@ "description": "招式命中率增加{{accuracyAmount}} (最大100)。" }, "PokemonMultiHitModifierType": { - "description": "攻擊造成一次額外傷害,每次堆疊額外傷害\n分別衰減60/75/82.5%。" + "description": "攻擊以60/75/82.5%的傷害造成2/3/4次傷害。" }, "TmModifierType": { "name": "招式學習器 {{moveId}} - {{moveName}}", "description": "教會一隻寶可夢{{moveName}}。" }, "TmModifierTypeWithInfo": { - "name": "TM{{moveId}} - {{moveName}}", - "description": "教會一隻寶可夢{{moveName}}\n(Hold C or Shift for more info)。" + "name": "招式學習器{{moveId}} - {{moveName}}", + "description": "教會一隻寶可夢{{moveName}}\n(按住C或者Shift查看更多信息)" }, "EvolutionItemModifierType": { "description": "使某些寶可夢進化。" @@ -183,6 +183,10 @@ "name": "復活種子", "description": "受到技能攻擊傷害瀕死時,\n恢復該瀕死寶可夢的HP至1/2。" }, + "WHITE_HERB": { + "name": "白色香草", + "description": "當攜帶它的寶可夢能力降低時,\n僅能回到之前的狀態1次。" + }, "ETHER": { "name": "PP單項小補劑" }, @@ -310,19 +314,19 @@ }, "BERRY_POUCH": { "name": "樹果袋", - "description": "使用樹果時有30%的幾率不會消耗樹果。" + "description": "使用樹果時增加30%的幾率不會消耗樹果。" }, "FOCUS_BAND": { "name": "氣勢頭帶", - "description": "攜帶該道具的寶可夢有10%幾率在受到\n攻擊而將陷入瀕死狀態時,保留1點HP不陷入瀕死狀態。" + "description": "攜帶該道具的寶可夢增加10%幾率在受到\n攻擊而將陷入瀕死狀態時,保留1點HP不陷入瀕死狀態。" }, "QUICK_CLAW": { "name": "先制之爪", - "description": "有10%的幾率無視速度優先使出招式\n(先制技能優先)。" + "description": "增加10%的幾率無視速度優先使出招式\n(先制技能優先)。" }, "KINGS_ROCK": { "name": "王者之證", - "description": "攜帶該道具的寶可夢使用任意原本不會造成\n畏縮狀態的攻擊招式並造成傷害時,有\n10%幾率使目標陷入畏縮狀態。" + "description": "攜帶該道具的寶可夢使用任意原本不會造成\n畏縮狀態的攻擊招式並造成傷害時,增加\n10%幾率使目標陷入畏縮狀態。" }, "LEFTOVERS": { "name": "喫剩的東西", diff --git a/src/locales/zh_TW/modifier.json b/src/locales/zh_TW/modifier.json index 1c0d4760e6f..12c436c1783 100644 --- a/src/locales/zh_TW/modifier.json +++ b/src/locales/zh_TW/modifier.json @@ -3,6 +3,7 @@ "turnHealApply": "{{pokemonNameWithAffix}}用{{typeName}}\n回復了體力!", "hitHealApply": "{{pokemonNameWithAffix}}用{{typeName}}\n回復了體力!", "pokemonInstantReviveApply": "{{pokemonNameWithAffix}}用{{typeName}}\n回復了活力!", + "pokemonResetNegativeStatStageApply": "{{pokemonNameWithAffix}}降低的能力被{{typeName}}\n複原了!!", "moneyInterestApply": "用{{typeName}}\n獲得了 ₽{{moneyAmount}} 利息!", "turnHeldItemTransferApply": "{{pokemonNameWithAffix}}的{{itemName}}被\n{{pokemonName}}的{{typeName}}吸收了!", "contactHeldItemTransferApply": "{{pokemonNameWithAffix}}的{{itemName}}被\n{{pokemonName}}的{{typeName}}奪取了!", diff --git a/src/locales/zh_TW/move-trigger.json b/src/locales/zh_TW/move-trigger.json index d6d0ce659ea..db88f6df57f 100644 --- a/src/locales/zh_TW/move-trigger.json +++ b/src/locales/zh_TW/move-trigger.json @@ -42,12 +42,12 @@ "incineratedItem": "{{pokemonName}}燒掉了\n{{targetName}}的{{itemName}}!", "knockedOffItem": "{{pokemonName}}拍落了\n{{targetName}}的{{itemName}}!", "tookMoveAttack": "{{pokemonName}}\n受到了{{moveName}}的攻擊!", - "cutOwnHpAndMaximizedStat": "{{pokemonName}}\n削減體力並釋放了全部{{statName}}!", + "cutOwnHpAndMaximizedStat": "{{pokemonName}}\n削減體力並釋放了全部{{statName}}!", "copiedStatChanges": "{{pokemonName}}複製了\n{{targetName}}的能力變化!", "magnitudeMessage": "震級{{magnitude}}!", "tookAimAtTarget": "{{pokemonName}}將目標對準了\n{{targetName}}!", "transformedIntoType": "{{pokemonName}} \n變成了{{typeName}}屬性!", - "copiedMove": "{{pokemonName}}\n複製了{{moveName}}!", + "copiedMove": "{{pokemonName}}\n複製了{{moveName}}!", "sketchedMove": "{{pokemonName}}\n對{{moveName}}進行了寫生!", "acquiredAbility": "{{pokemonName}}的特性\n變为{{abilityName}}了!", "copiedTargetAbility": "{{pokemonName}}複製了\n{{targetName}}的{{abilityName}}!", @@ -66,5 +66,6 @@ "revivalBlessing": "{{pokemonName}}復活了!", "swapArenaTags": "{{pokemonName}}\n交換了雙方的場地效果!", "exposedMove": "{{pokemonName}}識破了\n{{targetPokemonName}}的原形!", - "safeguard": "{{targetName}}\n正受到神秘之幕的保護!" -} \ No newline at end of file + "safeguard": "{{targetName}}\n正受到神秘之幕的保護!", + "afterYou": "{{pokemonName}}\n接受了對手的好意!" +} diff --git a/src/locales/zh_TW/move.json b/src/locales/zh_TW/move.json index 101d6f85e5d..b8c4ec05033 100644 --- a/src/locales/zh_TW/move.json +++ b/src/locales/zh_TW/move.json @@ -2913,7 +2913,7 @@ }, "zippyZap": { "name": "電電加速", - "effect": "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness." + "effect": "迅猛無比的電擊。必定能夠先制攻擊,\n並且提高自己的閃避率" }, "splishySplash": { "name": "滔滔衝浪", @@ -3807,4 +3807,4 @@ "name": "邪毒鎖鏈", "effect": "用由毒形成的鎖鏈纏住對手\n注入毒素加以侵蝕。有時會\n讓對手陷入劇毒狀態" } -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/party-ui-handler.json b/src/locales/zh_TW/party-ui-handler.json index 975212bbdad..ef82d1a3ddc 100644 --- a/src/locales/zh_TW/party-ui-handler.json +++ b/src/locales/zh_TW/party-ui-handler.json @@ -4,5 +4,44 @@ "CANCEL": "取消", "RELEASE": "放生", "APPLY": "應用", - "TEACH": "教授" -} \ No newline at end of file + "TEACH": "教授", + "SPLICE": "融合", + "UNSPLICE": "分離", + "ACTIVATE": "激活", + "DEACTIVATE": "解除", + "TRANSFER": "交換", + "ALL": "全部道具", + "PASS_BATON": "接棒", + "UNPAUSE_EVOLUTION": "解除進化暫停", + "REVIVE": "複活", + "RENAME": "起名", + "choosePokemon": "選擇一只寶可夢。", + "doWhatWithThisPokemon": "要對寶可夢做什麽?", + "noEnergy": "{{pokemonName}}沒有力氣戰鬥了!", + "hasEnergy": "{{pokemonName}}仍然精神十足!", + "cantBeUsed": "{{pokemonName}}無法在此挑戰中使用!", + "tooManyItems": "{{pokemonName}}擁有\n太多這個道具了!", + "anyEffect": "即便使用也無效果哦。", + "unpausedEvolutions": "{{pokemonName}}的進化停止了。", + "unspliceConfirmation": "真的要把{{fusionName}}\n從{{pokemonName}}身上分離嗎?{{fusionName}}會就此消失。", + "wasReverted": "{{fusionName}}恢複成了{{pokemonName}}。", + "releaseConfirmation": "你真要放生{{pokemonName}}嗎?", + "releaseInBattle": "你無法放生正在戰鬥中的寶可夢!", + "selectAMove": "選擇一個招式。", + "changeQuantity": "選擇一件道具來交換。\n使用 ← 和 → 來指定數量。", + "selectAnotherPokemonToSplice": "選擇另一只寶可夢來融合。", + "cancel": "取消", + "able": "能學會!", + "notAble": "無法學習", + "learned": "已習得", + "goodbye": "再見,{{pokemonName}}!", + "byebye": "拜拜,{{pokemonName}}!", + "farewell": "再會了,{{pokemonName}}!", + "soLong": "告辭了,{{pokemonName}}!", + "thisIsWhereWePart": "就此分別吧,{{pokemonName}}!", + "illMissYou": "我會想你的,{{pokemonName}}!", + "illNeverForgetYou": "我不會忘記你的,{{pokemonName}}!", + "untilWeMeetAgain": "下次再見了,{{pokemonName}}!", + "sayonara": "撒由那拉,{{pokemonName}}!", + "smellYaLater": "拜拜了您勒,{{pokemonName}}!" +} diff --git a/src/locales/zh_TW/pokemon-form-battle.json b/src/locales/zh_TW/pokemon-form-battle.json index 75087aa0669..93a9e65f1f8 100644 --- a/src/locales/zh_TW/pokemon-form-battle.json +++ b/src/locales/zh_TW/pokemon-form-battle.json @@ -2,13 +2,13 @@ "mega": "Mega {{pokemonName}}", "mega-x": "Mega {{pokemonName}} X", "mega-y": "Mega {{pokemonName}} Y", - "primal": "Primal {{pokemonName}}", - "gigantamax": "G-Max {{pokemonName}}", - "eternamax": "E-Max {{pokemonName}}", + "primal": "原始{{pokemonName}}", + "gigantamax": "超極巨{{pokemonName}}", + "eternamax": "無極巨{{pokemonName}}", "megaChange": "{{preName}}超級進化成了\n{{pokemonName}}!", "gigantamaxChange": "{{preName}}超極巨化成了\n{{pokemonName}}!", "eternamaxChange": "{{preName}}無極巨化成了\n{{pokemonName}}!", "revertChange": "{{pokemonName}}變回了\n原本的樣子!", "formChange": "{{preName}}變為其他樣子了。", "disguiseChange": "它的畫皮被當作誘餌使用了!" -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/pokemon-form.json b/src/locales/zh_TW/pokemon-form.json index b98a1e946b8..f1fb4dff599 100644 --- a/src/locales/zh_TW/pokemon-form.json +++ b/src/locales/zh_TW/pokemon-form.json @@ -1,3 +1,170 @@ { - "meloettaPirouette": "舞步形態" -} \ No newline at end of file + "pikachuCosplay": "換裝", + "pikachuCoolCosplay": "搖滾巨星", + "pikachuBeautyCosplay": "貴婦", + "pikachuCuteCosplay": "流行偶像", + "pikachuSmartCosplay": "博士", + "pikachuToughCosplay": "面罩摔跤手", + "pikachuPartner": "搭檔", + "eeveePartner": "搭檔", + "pichuSpiky": "刺刺耳", + "unownA": "A", + "unownB": "B", + "unownC": "C", + "unownD": "D", + "unownE": "E", + "unownF": "F", + "unownG": "G", + "unownH": "H", + "unownI": "I", + "unownJ": "J", + "unownK": "K", + "unownL": "L", + "unownM": "M", + "unownN": "N", + "unownO": "O", + "unownP": "P", + "unownQ": "Q", + "unownR": "R", + "unownS": "S", + "unownT": "T", + "unownU": "U", + "unownV": "V", + "unownW": "W", + "unownX": "X", + "unownY": "Y", + "unownZ": "Z", + "unownExclamation": "!", + "unownQuestion": "?", + "castformSunny": "晴天", + "castformRainy": "雨天", + "castformSnowy": "雪天", + "deoxysNormal": "普通", + "burmyPlant": "草木蓑衣", + "burmySandy": "砂土蓑衣", + "burmyTrash": "垃圾蓑衣", + "shellosEast": "東海", + "shellosWest": "西海", + "rotomHeat": "加熱", + "rotomWash": "清洗", + "rotomFrost": "結冰", + "rotomFan": "旋轉", + "rotomMow": "切割", + "giratinaAltered": "別種", + "shayminLand": "陸上", + "basculinRedStriped": "紅條紋", + "basculinBlueStriped": "藍條紋", + "basculinWhiteStriped": "白條紋", + "deerlingSpring": "春天", + "deerlingSummer": "夏天", + "deerlingAutumn": "秋天", + "deerlingWinter": "冬天", + "tornadusIncarnate": "化身", + "thundurusIncarnate": "化身", + "landorusIncarnate": "化身", + "keldeoOrdinary": "通常", + "meloettaAria": "歌聲", + "meloettaPirouette": "舞步形態", + "froakieBattleBond": "牽絆變身", + "scatterbugMeadow": "花園花紋", + "scatterbugIcySnow": "冰雪花紋", + "scatterbugPolar": "雪國花紋", + "scatterbugTundra": "雪原花紋", + "scatterbugContinental": "大陸花紋", + "scatterbugGarden": "庭園花紋", + "scatterbugElegant": "高雅花紋", + "scatterbugModern": "摩登花紋", + "scatterbugMarine": "大海花紋", + "scatterbugArchipelago": "群島花紋", + "scatterbugHighPlains": "荒野花紋", + "scatterbugSandstorm": "沙塵花紋", + "scatterbugRiver": "大河花紋", + "scatterbugMonsoon": "驟雨花紋", + "scatterbugSavanna": "熱帶草原花紋", + "scatterbugSun": "太陽花紋", + "scatterbugOcean": "大洋花紋", + "scatterbugJungle": "熱帶雨林花紋", + "scatterbugFancy": "幻彩花紋", + "scatterbugPokeBall": "球球花紋", + "flabebeRed": "紅花", + "flabebeYellow": "黃花", + "flabebeOrange": "橙花", + "flabebeBlue": "藍花", + "flabebeWhite": "白花", + "furfrouHeart": "心形造型", + "furfrouStar": "星形造型", + "furfrouDiamond": "菱形造型", + "furfrouDebutante": "淑女造型", + "furfrouMatron": "貴婦造型", + "furfrouDandy": "紳士造型", + "furfrouLaReine": "女王造型", + "furfrouKabuki": "歌舞伎造型", + "furfrouPharaoh": "國王造型", + "pumpkabooSmall": "小尺寸", + "pumpkabooLarge": "大尺寸", + "pumpkabooSuper": "特大尺寸", + "xerneasNeutral": "放松模式", + "xerneasActive": "活躍模式", + "zygarde50": "50%形態", + "zygarde10": "10%形態", + "zygarde50Pc": "50%形態 群聚變形", + "zygarde10Pc": "10%形態 群聚變形", + "zygardeComplete": "完全體形態", + "oricorioBaile": "熱辣熱辣風格", + "oricorioPompom": "啪滋啪滋風格", + "oricorioPau": "呼拉呼拉風格", + "oricorioSensu": "輕盈輕盈風格", + "rockruffOwnTempo": "特殊岩狗狗", + "miniorRedMeteor": "紅色核心", + "miniorOrangeMeteor": "橙色核心", + "miniorYellowMeteor": "黃色核心", + "miniorGreenMeteor": "綠色核心", + "miniorBlueMeteor": "淺藍色核心", + "miniorIndigoMeteor": "藍色核心", + "miniorVioletMeteor": "紫色核心", + "miniorRed": "紅色", + "miniorOrange": "橙色", + "miniorYellow": "黃色", + "miniorGreen": "綠色", + "miniorBlue": "淺藍色", + "miniorIndigo": "藍色", + "miniorViolet": "紫色", + "mimikyuDisguised": "化形", + "mimikyuBusted": "現形", + "magearnaOriginal": "500年前的顔色", + "marshadowZenith": "全力", + "sinisteaPhony": "赝品", + "sinisteaAntique": "真品", + "eiscueNoIce": "解凍頭", + "indeedeeMale": "雄性", + "indeedeeFemale": "雌性", + "morpekoFullBelly": "滿腹花紋", + "zacianHeroOfManyBattles": "百戰勇者", + "zamazentaHeroOfManyBattles": "百戰勇者", + "zarudeDada": "老爹", + "enamorusIncarnate": "化身", + "squawkabillyGreenPlumage": "綠羽毛", + "squawkabillyBluePlumage": "藍羽毛", + "squawkabillyYellowPlumage": "黃羽毛", + "squawkabillyWhitePlumage": "白羽毛", + "tatsugiriCurly": "上弓姿勢", + "tatsugiriDroopy": "下垂姿勢", + "tatsugiriStretchy": "平挺姿勢", + "gimmighoulChest": "寶箱形態", + "gimmighoulRoaming": "徒步形態", + "koraidonApexBuild": "頂尖形態", + "koraidonLimitedBuild":"限制形態", + "koraidonSprintingBuild":"沖刺形態", + "koraidonSwimmingBuild":"遊泳形態", + "koraidonGlidingBuild":"滑翔形態", + "miraidonUltimateMode":"極限模式", + "miraidonLowPowerMode":"節能模式", + "miraidonDriveMode":"駕駛模式", + "miraidonAquaticMode":"水上模式", + "miraidonGlideMode":"滑翔模式", + "poltchageistCounterfeit": "冒牌貨", + "poltchageistArtisan": "高檔貨", + "paldeaTaurosCombat": "鬥戰種", + "paldeaTaurosBlaze": "火熾種", + "paldeaTaurosAqua": "水瀾種" +} diff --git a/src/locales/zh_TW/pokemon-info.json b/src/locales/zh_TW/pokemon-info.json index 66a99857a82..f2e29875e75 100644 --- a/src/locales/zh_TW/pokemon-info.json +++ b/src/locales/zh_TW/pokemon-info.json @@ -11,7 +11,9 @@ "SPDEF": "特殊防禦", "SPDEFshortened": "特防", "SPD": "速度", - "SPDshortened": "速度" + "SPDshortened": "速度", + "ACC": "命中率", + "EVA": "回避率" }, "Type": { "UNKNOWN": "未知", @@ -35,4 +37,4 @@ "FAIRY": "妖精", "STELLAR": "星晶" } -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/pokemon-summary.json b/src/locales/zh_TW/pokemon-summary.json index 9e26dfeeb6e..ddbbea63a3a 100644 --- a/src/locales/zh_TW/pokemon-summary.json +++ b/src/locales/zh_TW/pokemon-summary.json @@ -1 +1,45 @@ -{} \ No newline at end of file +{ + "pokemonInfo": "寶可夢信息", + "status": "狀態", + "powerAccuracyCategory": "威力\n命中率\n類別", + "type": "屬性", + "unknownTrainer": "未知", + "ot": "訓練師", + "nature": "性格", + "expPoints": "經驗值", + "nextLv": "下一級", + "cancel": "取消", + + "memoString": "{{natureFragment}} 性格,\n{{metFragment}}", + "metFragment": { + "normal": "met at Lv{{level}},\n{{biome}}.", + "apparently": "命中注定般地相遇于Lv.{{level}},\n{{biome}}。" + }, + "natureFragment": { + "Hardy": "{{nature}}", + "Lonely": "{{nature}}", + "Brave": "{{nature}}", + "Adamant": "{{nature}}", + "Naughty": "{{nature}}", + "Bold": "{{nature}}", + "Docile": "{{nature}}", + "Relaxed": "{{nature}}", + "Impish": "{{nature}}", + "Lax": "{{nature}}", + "Timid": "{{nature}}", + "Hasty": "{{nature}}", + "Serious": "{{nature}}", + "Jolly": "{{nature}}", + "Naive": "{{nature}}", + "Modest": "{{nature}}", + "Mild": "{{nature}}", + "Quiet": "{{nature}}", + "Bashful": "{{nature}}", + "Rash": "{{nature}}", + "Calm": "{{nature}}", + "Gentle": "{{nature}}", + "Sassy": "{{nature}}", + "Careful": "{{nature}}", + "Quirky": "{{nature}}" + } +} diff --git a/src/locales/zh_TW/settings.json b/src/locales/zh_TW/settings.json index b077e0216a3..d9c71df3a0d 100644 --- a/src/locales/zh_TW/settings.json +++ b/src/locales/zh_TW/settings.json @@ -95,5 +95,7 @@ "mute": "靜音", "controller": "控制器", "gamepadSupport": "手柄支持", - "moveTouchControls": "移動觸控控制" + "showBgmBar": "顯示音樂名稱", + "moveTouchControls": "移動觸控控制", + "shopOverlayOpacity": "商店顯示不透明度" } diff --git a/src/locales/zh_TW/splash-messages.json b/src/locales/zh_TW/splash-messages.json index 8535a9acd84..a25e7dab97b 100644 --- a/src/locales/zh_TW/splash-messages.json +++ b/src/locales/zh_TW/splash-messages.json @@ -31,5 +31,6 @@ "alsoTryEmeraldRogue": "也試試翡翠流氓!", "alsoTryRadicalRed": "也試試激進紅!", "eeveeExpo": "伊布博覽會!", - "ynoproject": "YNO專案!" -} \ No newline at end of file + "ynoproject": "YNO專案!", + "breedersInSpace": "飼養員也能上太空?" +} diff --git a/src/locales/zh_TW/starter-select-ui-handler.json b/src/locales/zh_TW/starter-select-ui-handler.json index 2a0db7217da..ad64a8d9743 100644 --- a/src/locales/zh_TW/starter-select-ui-handler.json +++ b/src/locales/zh_TW/starter-select-ui-handler.json @@ -1,6 +1,7 @@ { - "confirmStartTeam": "使用這些寶可夢開始嗎?", - "invalidParty": "此為無效隊伍!", + "confirmStartTeam": "使用這些寶可夢開始嗎?", + "confirmExit": "確定要退出嗎?", + "invalidParty": "此為無效隊伍!", "gen1": "I", "gen2": "II", "gen3": "III", @@ -21,6 +22,8 @@ "toggleIVs": "查看個體值", "manageMoves": "管理技能", "manageNature": "管理性格", + "addToFavorites": "添加到最愛", + "removeFromFavorites": "移出最愛", "useCandies": "使用糖果", "selectNature": "選擇性格", "selectMoveSwapOut": "選擇想要替換走的招式", @@ -40,4 +43,4 @@ "locked": "未解鎖", "disabled": "已禁用", "uncaught": "未捕獲" -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/status-effect.json b/src/locales/zh_TW/status-effect.json index 9e26dfeeb6e..5f634a0bddf 100644 --- a/src/locales/zh_TW/status-effect.json +++ b/src/locales/zh_TW/status-effect.json @@ -1 +1,65 @@ -{} \ No newline at end of file +{ + "none": { + "name": "無", + "description": "", + "obtain": "", + "obtainSource": "", + "activation": "", + "overlap": "", + "heal": "" + }, + "poison": { + "name": "中毒", + "description": "中毒", + "obtain": "{{pokemonNameWithAffix}}中毒了!", + "obtainSource": "{{pokemonNameWithAffix}}因{{sourceText}}中毒了!", + "activation": "{{pokemonNameWithAffix}}受到了毒的傷害!", + "overlap": "{{pokemonNameWithAffix}}已經中毒了!", + "heal": "{{pokemonNameWithAffix}}中的毒徹底清除了!" + }, + "toxic": { + "name": "劇毒", + "description": "中毒", + "obtain": "{{pokemonNameWithAffix}}中了劇毒!", + "obtainSource": "{{pokemonNameWithAffix}}因{{sourceText}}中了劇毒!", + "activation": "{{pokemonNameWithAffix}}受到了毒的傷害!", + "overlap": "{{pokemonNameWithAffix}}已經中毒了!", + "heal": "{{pokemonNameWithAffix}}中的毒徹底清除了!" + }, + "paralysis": { + "name": "麻痹", + "description": "麻痹", + "obtain": "{{pokemonNameWithAffix}}麻痹了,很難使出招式!", + "obtainSource": "{{pokemonNameWithAffix}}被{{sourceText}}麻痹了,很難使出招式!", + "activation": "{{pokemonNameWithAffix}}因身體麻痹而無法行動!", + "overlap": "{{pokemonNameWithAffix}}已經麻痹了!", + "heal": "{{pokemonNameWithAffix}}的麻痹治愈了!" + }, + "sleep": { + "name": "睡眠", + "description": "睡眠", + "obtain": "{{pokemonNameWithAffix}}睡著了!", + "obtainSource": "{{pokemonNameWithAffix}}因{{sourceText}}睡著了!", + "activation": "{{pokemonNameWithAffix}}正在呼呼大睡。", + "overlap": "{{pokemonNameWithAffix}}已經睡著了!", + "heal": "{{pokemonNameWithAffix}}醒了!" + }, + "freeze": { + "name": "冰凍", + "description": "冰凍", + "obtain": "{{pokemonNameWithAffix}}凍住了!", + "obtainSource": "{{pokemonNameWithAffix}}因{{sourceText}}凍住了!", + "activation": "{{pokemonNameWithAffix}}因凍住了而無法行動!", + "overlap": "{{pokemonNameWithAffix}}已經凍住了!", + "heal": "{{pokemonNameWithAffix}}治愈了冰凍狀態!" + }, + "burn": { + "name": "灼傷", + "description": "灼傷", + "obtain": "{{pokemonNameWithAffix}}被灼傷了!", + "obtainSource": "{{pokemonNameWithAffix}}因{{sourceText}}被灼傷了!", + "activation": "{{pokemonNameWithAffix}}受到了灼傷的傷害!", + "overlap": "{{pokemonNameWithAffix}}已經被灼傷了!", + "heal": "{{pokemonNameWithAffix}}的灼傷治愈了!" + } +} diff --git a/src/locales/zh_TW/trainer-classes.json b/src/locales/zh_TW/trainer-classes.json index d6ff7238ec1..d0b0fed7e5d 100644 --- a/src/locales/zh_TW/trainer-classes.json +++ b/src/locales/zh_TW/trainer-classes.json @@ -100,6 +100,8 @@ "worker_female": "工人", "workers": "工人組合", "youngster": "短褲小子", + "rocket_grunt": "火箭队手下", + "rocket_grunt_female": "火箭队手下", "rocket_grunts": "火箭队手下們", "magma_grunt": "熔岩队手下", "magma_grunt_female": "熔岩队手下", @@ -116,4 +118,4 @@ "flare_grunt": "闪焰队手下", "flare_grunt_female": "闪焰队手下", "flare_grunts": "闪焰队手下們" -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/trainer-names.json b/src/locales/zh_TW/trainer-names.json index 64e8892e64b..04399cf19af 100644 --- a/src/locales/zh_TW/trainer-names.json +++ b/src/locales/zh_TW/trainer-names.json @@ -123,6 +123,34 @@ "kieran": "烏栗", "rival": "芬恩", "rival_female": "艾薇", + "archer": "阿波羅", + "ariana": "雅典娜", + "proton": "蘭斯", + "petrel": "拉姆達", + "tabitha": "火村", + "courtney": "火雁", + "shelly": "阿泉", + "matt": "阿潮", + "mars": "夥星", + "jupiter": "碎星", + "saturn": "鎮星", + "zinzolin": "維奧", + "rood": "羅德", + "xerosic": "庫瑟洛斯奇", + "bryony": "芭拉", + "faba": "扎奧博", + "plumeria": "布爾美麗", + "oleana": "奧利薇", + + "maxie": "赤焰松", + "archie": "水梧桐", + "cyrus": "赤日", + "ghetsis": "魁奇思", + "lysandre": "弗拉達利", + "lusamine": "露莎米奈", + "guzma": "古茲馬", + "rose": "洛茲", + "blue_red_double": "青綠 & 赤紅", "red_blue_double": "赤紅 & 青綠", "tate_liza_double": "小楓 & 小南", @@ -133,4 +161,4 @@ "iris_alder_double": "艾莉絲 & 阿戴克", "marnie_piers_double": "瑪俐 & 聶梓", "piers_marnie_double": "聶梓 & 瑪俐" -} \ No newline at end of file +} diff --git a/src/locales/zh_TW/trainer-titles.json b/src/locales/zh_TW/trainer-titles.json index 54fe48b1464..80b2807e7b5 100644 --- a/src/locales/zh_TW/trainer-titles.json +++ b/src/locales/zh_TW/trainer-titles.json @@ -9,5 +9,24 @@ "champion_double": "冠軍搭檔", "rival": "勁敵", "professor": "博士", - "frontier_brain": "開拓頭腦" -} \ No newline at end of file + "frontier_brain": "開拓頭腦", + "rocket_boss": "火箭隊老大", + "magma_boss": "熔岩隊老大", + "aqua_boss": "海洋隊老大", + "galactic_boss": "銀河隊老大", + "plasma_boss": "等離子隊老大", + "flare_boss": "閃焰隊老大", + + "rocket_admin": "火箭隊幹部", + "rocket_admin_female": "火箭隊幹部", + "magma_admin": "熔岩隊幹部", + "magma_admin_female": "熔岩隊幹部", + "aqua_admin": "海洋隊幹部", + "aqua_admin_female": "海洋隊幹部", + "galactic_commander": "銀河隊幹部", + "galactic_commander_female": "銀河隊幹部", + "plasma_sage": "等離子隊賢人", + "plasma_admin": "等離子隊幹部", + "flare_admin": "閃焰隊幹部", + "flare_admin_female": "閃焰隊幹部" +} diff --git a/src/locales/zh_TW/weather.json b/src/locales/zh_TW/weather.json index b20975374ea..b315d27625d 100644 --- a/src/locales/zh_TW/weather.json +++ b/src/locales/zh_TW/weather.json @@ -27,5 +27,6 @@ "harshSunClearMessage": "日照復原了。", "strongWindsStartMessage": "吹起了神秘的亂流!", "strongWindsLapseMessage": "神秘的亂流勢頭不減。", + "strongWindsEffectMessage": "神秘的亂流減弱了攻擊!", "strongWindsClearMessage": "神秘的亂流停止了。" -} \ No newline at end of file +} From ce9a75f074a87815850d34bff8c33e6e6b06be0a Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Wed, 11 Sep 2024 13:54:42 -0700 Subject: [PATCH 02/16] Replace `vi.fn()` with `() => null` whenenver possible (#4182) --- src/test/utils/gameWrapper.ts | 2 +- src/test/utils/mocks/mockGameObjectCreator.ts | 5 ++--- src/test/utils/mocks/mockVideoGameObject.ts | 11 +++++------ src/test/utils/mocks/mocksContainer/mockContainer.ts | 10 ++++------ src/test/utils/mocks/mocksContainer/mockSprite.ts | 3 +-- src/test/utils/mocks/mocksContainer/mockText.ts | 11 +++++------ 6 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/test/utils/gameWrapper.ts b/src/test/utils/gameWrapper.ts index f3098fa9b71..1cf01a3a8c8 100644 --- a/src/test/utils/gameWrapper.ts +++ b/src/test/utils/gameWrapper.ts @@ -41,7 +41,7 @@ window.URL.createObjectURL = (blob: Blob) => { }); return null; }; -navigator.getGamepads = vi.fn().mockReturnValue([]); +navigator.getGamepads = () => []; global.fetch = vi.fn(MockFetch); Utils.setCookie(Utils.sessionIdKey, 'fake_token'); diff --git a/src/test/utils/mocks/mockGameObjectCreator.ts b/src/test/utils/mocks/mockGameObjectCreator.ts index 19406a46923..27860be0cec 100644 --- a/src/test/utils/mocks/mockGameObjectCreator.ts +++ b/src/test/utils/mocks/mockGameObjectCreator.ts @@ -1,4 +1,3 @@ -import { vi } from "vitest"; import MockGraphics from "./mocksContainer/mockGraphics"; import MockTextureManager from "./mockTextureManager"; @@ -16,8 +15,8 @@ export class MockGameObjectCreator { rexTransitionImagePack() { return { - transit: vi.fn(), - once: vi.fn(), + transit: () => null, + once: () => null, }; } } diff --git a/src/test/utils/mocks/mockVideoGameObject.ts b/src/test/utils/mocks/mockVideoGameObject.ts index 96f03542bbc..d8155e23b6c 100644 --- a/src/test/utils/mocks/mockVideoGameObject.ts +++ b/src/test/utils/mocks/mockVideoGameObject.ts @@ -1,13 +1,12 @@ -import { vi } from "vitest"; import { MockGameObject } from "./mockGameObject"; /** Mocks video-related stuff */ export class MockVideoGameObject implements MockGameObject { constructor() {} - public play = vi.fn(); - public stop = vi.fn(() => this); - public setOrigin = vi.fn(); - public setScale = vi.fn(); - public setVisible = vi.fn(); + public play = () => null; + public stop = () => this; + public setOrigin = () => null; + public setScale = () => null; + public setVisible = () => null; } diff --git a/src/test/utils/mocks/mocksContainer/mockContainer.ts b/src/test/utils/mocks/mocksContainer/mockContainer.ts index 94ae61a6ce4..e13cef0e43e 100644 --- a/src/test/utils/mocks/mocksContainer/mockContainer.ts +++ b/src/test/utils/mocks/mocksContainer/mockContainer.ts @@ -1,5 +1,4 @@ import MockTextureManager from "#test/utils/mocks/mockTextureManager"; -import { vi } from "vitest"; import { MockGameObject } from "../mockGameObject"; export default class MockContainer implements MockGameObject { @@ -52,7 +51,7 @@ export default class MockContainer implements MockGameObject { /// Sets the position of this Game Object to be a relative position from the source Game Object. } - setInteractive = vi.fn(); + setInteractive = () => null; setOrigin(x, y) { this.x = x; @@ -160,10 +159,9 @@ export default class MockContainer implements MockGameObject { // Moves this Game Object to be below the given Game Object in the display list. } - setName = vi.fn((name: string) => { + setName = (name: string) => { this.name = name; - // return this.phaserSprite.setName(name); - }); + }; bringToTop(obj) { // Brings this Game Object to the top of its parents display list. @@ -207,5 +205,5 @@ export default class MockContainer implements MockGameObject { return this.list; } - disableInteractive = vi.fn(); + disableInteractive = () => null; } diff --git a/src/test/utils/mocks/mocksContainer/mockSprite.ts b/src/test/utils/mocks/mocksContainer/mockSprite.ts index ae43df46cf5..83ec3951151 100644 --- a/src/test/utils/mocks/mocksContainer/mockSprite.ts +++ b/src/test/utils/mocks/mocksContainer/mockSprite.ts @@ -1,6 +1,5 @@ import Phaser from "phaser"; import { MockGameObject } from "../mockGameObject"; -import { vi } from "vitest"; import Sprite = Phaser.GameObjects.Sprite; import Frame = Phaser.Textures.Frame; @@ -102,7 +101,7 @@ export default class MockSprite implements MockGameObject { return this.phaserSprite.stop(); } - setInteractive = vi.fn(); + setInteractive = () => null; on(event, callback, source) { return this.phaserSprite.on(event, callback, source); diff --git a/src/test/utils/mocks/mocksContainer/mockText.ts b/src/test/utils/mocks/mocksContainer/mockText.ts index 5a89432902b..5462056f1e5 100644 --- a/src/test/utils/mocks/mocksContainer/mockText.ts +++ b/src/test/utils/mocks/mocksContainer/mockText.ts @@ -1,5 +1,4 @@ import UI from "#app/ui/ui"; -import { vi } from "vitest"; import { MockGameObject } from "../mockGameObject"; export default class MockText implements MockGameObject { @@ -193,11 +192,11 @@ export default class MockText implements MockGameObject { }; } - setColor = vi.fn((color: string) => { + setColor = (color: string) => { this.color = color; - }); + }; - setInteractive = vi.fn(); + setInteractive = () => null; setShadowColor(color) { // Sets the shadow color. @@ -223,9 +222,9 @@ export default class MockText implements MockGameObject { // return this.phaserText.setAlpha(alpha); } - setName = vi.fn((name: string) => { + setName = (name: string) => { this.name = name; - }); + }; setAlign(align) { // return this.phaserText.setAlign(align); From b33d86a1db18b1ec437368aa5accfd3a7e2e295d Mon Sep 17 00:00:00 2001 From: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:55:13 +0200 Subject: [PATCH 03/16] [BUG] Make Tate & Liza have seeded randomness #4175 --- src/field/trainer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 02827d0d69d..326ef0edefb 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -357,7 +357,7 @@ export default class Trainer extends Phaser.GameObjects.Container { // If useNewSpeciesPool is true, we need to generate a new species from the new species pool, otherwise we generate a random species let species = useNewSpeciesPool - ? getPokemonSpecies(newSpeciesPool[Math.floor(Math.random() * newSpeciesPool.length)]) + ? getPokemonSpecies(newSpeciesPool[Math.floor(Utils.randSeedInt(newSpeciesPool.length))]) : template.isSameSpecies(index) && index > offset ? getPokemonSpecies(battle.enemyParty[offset].species.getTrainerSpeciesForLevel(level, false, template.getStrength(offset), this.scene.currentBattle.waveIndex)) : this.genNewPartyMemberSpecies(level, strength); From 50a75005611b16ba5bfa4986395954e0f675adce Mon Sep 17 00:00:00 2001 From: chaosgrimmon <31082757+chaosgrimmon@users.noreply.github.com> Date: Wed, 11 Sep 2024 19:46:38 -0400 Subject: [PATCH 04/16] [Sprite] Fix animated Cursola (#4186) * [Sprite] Index Cursola exp * [Sprite] Index shiny Cursola exp * [Sprite] Update exp Cursola variant palette --- public/images/pokemon/exp/864.png | Bin 35956 -> 15466 bytes public/images/pokemon/exp/shiny/864.png | Bin 34329 -> 15853 bytes public/images/pokemon/variant/exp/864.json | 54 +++++++++------------ 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/public/images/pokemon/exp/864.png b/public/images/pokemon/exp/864.png index 036e2b9e40f093b9f75fdde24cf82f287ce15976..2776e938e827d222477b12979307c160d301585f 100644 GIT binary patch literal 15466 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 literal 35956 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 diff --git a/public/images/pokemon/exp/shiny/864.png b/public/images/pokemon/exp/shiny/864.png index 079b1f6a6817c5cd1872ea98741e983eb87043aa..66d648edf7910994f9adf8d013b0679e8735b380 100644 GIT binary patch delta 15559 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 Sy!~AaBPXpaRV85>{C@ygvXm15 literal 34329 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 WKlW6i&KPLS5Cs`k=}JlS!2b_j-OaH8 diff --git a/public/images/pokemon/variant/exp/864.json b/public/images/pokemon/variant/exp/864.json index cf8ae42b0fd..ccfc0f2d88d 100644 --- a/public/images/pokemon/variant/exp/864.json +++ b/public/images/pokemon/variant/exp/864.json @@ -3,44 +3,36 @@ "bcb9be": "ae4c95", "f9f2fc": "ffc0e5", "7b787c": "793d6d", - "e1dfe2": "e88cc5", - "d0cfd0": "ce6bac", - "b8b4ba": "d7d2f6", + "dcd9dd": "e88cc5", + "c9c0ce": "ce6bac", + "cbc2d1": "d7d2f6", "938f94": "b465b9", - "6c7275": "d3ffff", - "9362e6": "80a4ff", - "fcfcfc": "fcfcfc", - "4a494e": "a7e6e5", - "c6a4ff": "bed5ff", - "101010": "101010", - "3b3a3f": "4d8894", - "aeadae": "e88cc5", - "686568": "686568", - "6f6d71": "793d6d", - "b5b4b6": "ce6bac", - "706e6d": "7d7c75", + "fbf2ff": "d3ffff", + "e66294": "80a4ff", + "c6bbcb": "a7e6e5", + "ffa4c5": "bed5ff", + "7f806a": "4d8894", + "a8a0ac": "e88cc5", + "7c7a78": "793d6d", + "bbb4bc": "ce6bac", "af9e9e": "42a2b1" }, "2": { "bcb9be": "055946", "f9f2fc": "21be70", "7b787c": "004140", - "e1dfe2": "12a169", - "d0cfd0": "0a7a57", - "b8b4ba": "567f83", + "dcd9dd": "12a169", + "c9c0ce": "0a7a57", + "cbc2d1": "567f83", "938f94": "2b5458", - "6c7275": "874059", - "9362e6": "15c05f", - "fcfcfc": "fcfcfc", - "4a494e": "773050", - "c6a4ff": "8ff3a3", - "101010": "101010", - "3b3a3f": "4b1f28", - "aeadae": "12a169", - "686568": "686568", - "6f6d71": "004140", - "b5b4b6": "0a7a57", - "706e6d": "7d7c75", + "fbf2ff": "874059", + "e66294": "15c05f", + "c6bbcb": "773050", + "ffa4c5": "8ff3a3", + "7f806a": "4b1f28", + "a8a0ac": "12a169", + "7c7a78": "004140", + "bbb4bc": "0a7a57", "af9e9e": "48c492" } -} \ No newline at end of file +} From a6d5fc66f276674cfff9e77b8c3037697359094c Mon Sep 17 00:00:00 2001 From: "Amani H." <109637146+xsn34kzx@users.noreply.github.com> Date: Wed, 11 Sep 2024 20:56:58 -0400 Subject: [PATCH 05/16] =?UTF-8?q?[Balance]=20Disable=20Eviolite=20for=20G-?= =?UTF-8?q?Max=20Pok=C3=A9mon=20(#4184)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Balance] Disable Eviolite for G-Max Pokémon * Add Documentation --- src/modifier/modifier.ts | 13 ++ src/test/items/eviolite.test.ts | 279 ++++++++++++++------------------ 2 files changed, 135 insertions(+), 157 deletions(-) diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index f5c80618396..9273eb42b90 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -29,6 +29,7 @@ import { Abilities } from "#app/enums/abilities"; import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { LevelUpPhase } from "#app/phases/level-up-phase"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; +import { SpeciesFormKey } from "#app/data/pokemon-species"; export type ModifierPredicate = (modifier: Modifier) => boolean; @@ -923,6 +924,18 @@ export class EvolutionStatBoosterModifier extends StatBoosterModifier { return modifier instanceof EvolutionStatBoosterModifier; } + /** + * Checks if the stat boosts can apply and if the holder is not currently + * Gigantamax'd. + * @param args [0] {@linkcode Pokemon} that holds the held item + * [1] {@linkcode Stat} N/A + * [2] {@linkcode Utils.NumberHolder} N/A + * @returns true if the stat boosts can be applied, false otherwise + */ + shouldApply(args: any[]): boolean { + return super.shouldApply(args) && ((args[0] as Pokemon).getFormKey() !== SpeciesFormKey.GIGANTAMAX); + } + /** * Boosts the incoming stat value by a {@linkcode multiplier} if the holder * can evolve. Note that, if the holder is a fusion, they will receive diff --git a/src/test/items/eviolite.test.ts b/src/test/items/eviolite.test.ts index 83b00583893..d9991d47a89 100644 --- a/src/test/items/eviolite.test.ts +++ b/src/test/items/eviolite.test.ts @@ -1,16 +1,15 @@ import { Stat } from "#enums/stat"; -import { EvolutionStatBoosterModifier } from "#app/modifier/modifier"; -import { modifierTypes } from "#app/modifier/modifier-type"; -import i18next from "#app/plugins/i18n"; -import * as Utils from "#app/utils"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; +import * as Utils from "#app/utils"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { StatBoosterModifier } from "#app/modifier/modifier"; describe("Items - Eviolite", () => { let phaserGame: Phaser.Game; let game: GameManager; + const TIMEOUT = 20 * 1000; beforeAll(() => { phaserGame = new Phase.Game({ @@ -25,108 +24,65 @@ describe("Items - Eviolite", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.battleType("single"); + game.override + .battleType("single") + .startingHeldItems([{ name: "EVIOLITE" }]); }); - it("EVIOLITE activates in battle correctly", async() => { - game.override.startingHeldItems([{ name: "EVIOLITE" }]); - const consoleSpy = vi.spyOn(console, "log"); - await game.startBattle([ + it("should provide 50% boost to DEF and SPDEF for unevolved, unfused pokemon", async() => { + await game.classicMode.startBattle([ Species.PICHU ]); - const partyMember = game.scene.getParty()[0]; + const partyMember = game.scene.getPlayerPokemon()!; - // Checking console log to make sure Eviolite is applied when getEffectiveStat (with the appropriate stat) is called - partyMember.getEffectiveStat(Stat.DEF); - expect(consoleSpy).toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), ""); + vi.spyOn(partyMember, "getEffectiveStat").mockImplementation((stat, _opponent?, _move?, _isCritical?) => { + const statValue = new Utils.NumberHolder(partyMember.getStat(stat, false)); + game.scene.applyModifiers(StatBoosterModifier, partyMember.isPlayer(), partyMember, stat, statValue); - // Printing dummy console messages along the way so subsequent checks don't pass because of the first - console.log(""); + // Ignore other calculations for simplicity - partyMember.getEffectiveStat(Stat.SPDEF); - expect(consoleSpy).toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), ""); + return Math.floor(statValue.value); + }); - console.log(""); + const defStat = partyMember.getStat(Stat.DEF, false); + const spDefStat = partyMember.getStat(Stat.SPDEF, false); - partyMember.getEffectiveStat(Stat.ATK); - expect(consoleSpy).not.toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), ""); + expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.5)); + expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.5)); + }, TIMEOUT); - console.log(""); - - partyMember.getEffectiveStat(Stat.SPATK); - expect(consoleSpy).not.toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), ""); - - console.log(""); - - partyMember.getEffectiveStat(Stat.SPD); - expect(consoleSpy).not.toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), ""); - }); - - it("EVIOLITE held by unevolved, unfused pokemon", async() => { - await game.startBattle([ - Species.PICHU - ]); - - const partyMember = game.scene.getParty()[0]; - - const defStat = partyMember.getStat(Stat.DEF); - const spDefStat = partyMember.getStat(Stat.SPDEF); - - // Making sure modifier is not applied without holding item - const defValue = new Utils.NumberHolder(defStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - const spDefValue = new Utils.NumberHolder(spDefStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); - - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); - - // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); - - expect(defValue.value / defStat).toBe(1.5); - expect(spDefValue.value / spDefStat).toBe(1.5); - }, 20000); - - it("EVIOLITE held by fully evolved, unfused pokemon", async() => { - await game.startBattle([ + it("should not provide a boost for fully evolved, unfused pokemon", async() => { + await game.classicMode.startBattle([ Species.RAICHU, ]); const partyMember = game.scene.getParty()[0]; - const defStat = partyMember.getStat(Stat.DEF); - const spDefStat = partyMember.getStat(Stat.SPDEF); + vi.spyOn(partyMember, "getEffectiveStat").mockImplementation((stat, _opponent?, _move?, _isCritical?) => { + const statValue = new Utils.NumberHolder(partyMember.getStat(stat, false)); + game.scene.applyModifiers(StatBoosterModifier, partyMember.isPlayer(), partyMember, stat, statValue); - // Making sure modifier is not applied without holding item - const defValue = new Utils.NumberHolder(defStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - const spDefValue = new Utils.NumberHolder(spDefStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + // Ignore other calculations for simplicity - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); + return Math.floor(statValue.value); + }); - // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + const defStat = partyMember.getStat(Stat.DEF, false); + const spDefStat = partyMember.getStat(Stat.SPDEF, false); - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); - }, 20000); + expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(defStat); + expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(spDefStat); - it("EVIOLITE held by completely unevolved, fused pokemon", async() => { - await game.startBattle([ + }, TIMEOUT); + + it("should provide 50% boost to DEF and SPDEF for completely unevolved, fused pokemon", async() => { + await game.classicMode.startBattle([ Species.PICHU, Species.CLEFFA ]); - const partyMember = game.scene.getParty()[0]; - const ally = game.scene.getParty()[1]; + const [ partyMember, ally ] = game.scene.getParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -137,35 +93,29 @@ describe("Items - Eviolite", () => { partyMember.fusionGender = ally.gender; partyMember.fusionLuck = ally.luck; - const defStat = partyMember.getStat(Stat.DEF); - const spDefStat = partyMember.getStat(Stat.SPDEF); + vi.spyOn(partyMember, "getEffectiveStat").mockImplementation((stat, _opponent?, _move?, _isCritical?) => { + const statValue = new Utils.NumberHolder(partyMember.getStat(stat, false)); + game.scene.applyModifiers(StatBoosterModifier, partyMember.isPlayer(), partyMember, stat, statValue); - // Making sure modifier is not applied without holding item - const defValue = new Utils.NumberHolder(defStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - const spDefValue = new Utils.NumberHolder(spDefStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + // Ignore other calculations for simplicity - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); + return Math.floor(statValue.value); + }); - // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + const defStat = partyMember.getStat(Stat.DEF, false); + const spDefStat = partyMember.getStat(Stat.SPDEF, false); - expect(defValue.value / defStat).toBe(1.5); - expect(spDefValue.value / spDefStat).toBe(1.5); - }, 20000); + expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.5)); + expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.5)); + }, TIMEOUT); - it("EVIOLITE held by partially unevolved (base), fused pokemon", async() => { - await game.startBattle([ + it("should provide 25% boost to DEF and SPDEF for partially unevolved (base), fused pokemon", async() => { + await game.classicMode.startBattle([ Species.PICHU, Species.CLEFABLE ]); - const partyMember = game.scene.getParty()[0]; - const ally = game.scene.getParty()[1]; + const [ partyMember, ally ] = game.scene.getParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -176,35 +126,29 @@ describe("Items - Eviolite", () => { partyMember.fusionGender = ally.gender; partyMember.fusionLuck = ally.luck; - const defStat = partyMember.getStat(Stat.DEF); - const spDefStat = partyMember.getStat(Stat.SPDEF); + vi.spyOn(partyMember, "getEffectiveStat").mockImplementation((stat, _opponent?, _move?, _isCritical?) => { + const statValue = new Utils.NumberHolder(partyMember.getStat(stat, false)); + game.scene.applyModifiers(StatBoosterModifier, partyMember.isPlayer(), partyMember, stat, statValue); - // Making sure modifier is not applied without holding item - const defValue = new Utils.NumberHolder(defStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - const spDefValue = new Utils.NumberHolder(spDefStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + // Ignore other calculations for simplicity - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); + return Math.floor(statValue.value); + }); - // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + const defStat = partyMember.getStat(Stat.DEF, false); + const spDefStat = partyMember.getStat(Stat.SPDEF, false); - expect(defValue.value / defStat).toBe(1.25); - expect(spDefValue.value / spDefStat).toBe(1.25); - }, 20000); + expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.25)); + expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.25)); + }, TIMEOUT); - it("EVIOLITE held by partially unevolved (fusion), fused pokemon", async() => { - await game.startBattle([ + it("should provide 25% boost to DEF and SPDEF for partially unevolved (fusion), fused pokemon", async() => { + await game.classicMode.startBattle([ Species.RAICHU, Species.CLEFFA ]); - const partyMember = game.scene.getParty()[0]; - const ally = game.scene.getParty()[1]; + const [ partyMember, ally ] = game.scene.getParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -215,35 +159,29 @@ describe("Items - Eviolite", () => { partyMember.fusionGender = ally.gender; partyMember.fusionLuck = ally.luck; - const defStat = partyMember.getStat(Stat.DEF); - const spDefStat = partyMember.getStat(Stat.SPDEF); + vi.spyOn(partyMember, "getEffectiveStat").mockImplementation((stat, _opponent?, _move?, _isCritical?) => { + const statValue = new Utils.NumberHolder(partyMember.getStat(stat, false)); + game.scene.applyModifiers(StatBoosterModifier, partyMember.isPlayer(), partyMember, stat, statValue); - // Making sure modifier is not applied without holding item - const defValue = new Utils.NumberHolder(defStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - const spDefValue = new Utils.NumberHolder(spDefStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + // Ignore other calculations for simplicity - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); + return Math.floor(statValue.value); + }); - // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + const defStat = partyMember.getStat(Stat.DEF, false); + const spDefStat = partyMember.getStat(Stat.SPDEF, false); - expect(defValue.value / defStat).toBe(1.25); - expect(spDefValue.value / spDefStat).toBe(1.25); - }, 20000); + expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(Math.floor(defStat * 1.25)); + expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(spDefStat * 1.25)); + }, TIMEOUT); - it("EVIOLITE held by completely evolved, fused pokemon", async() => { - await game.startBattle([ + it("should not provide a boost for fully evolved, fused pokemon", async() => { + await game.classicMode.startBattle([ Species.RAICHU, Species.CLEFABLE ]); - const partyMember = game.scene.getParty()[0]; - const ally = game.scene.getParty()[1]; + const [ partyMember, ally ] = game.scene.getParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -254,24 +192,51 @@ describe("Items - Eviolite", () => { partyMember.fusionGender = ally.gender; partyMember.fusionLuck = ally.luck; - const defStat = partyMember.getStat(Stat.DEF); - const spDefStat = partyMember.getStat(Stat.SPDEF); + vi.spyOn(partyMember, "getEffectiveStat").mockImplementation((stat, _opponent?, _move?, _isCritical?) => { + const statValue = new Utils.NumberHolder(partyMember.getStat(stat, false)); + game.scene.applyModifiers(StatBoosterModifier, partyMember.isPlayer(), partyMember, stat, statValue); - // Making sure modifier is not applied without holding item - const defValue = new Utils.NumberHolder(defStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - const spDefValue = new Utils.NumberHolder(spDefStat); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + // Ignore other calculations for simplicity - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); + return Math.floor(statValue.value); + }); - // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue); - partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue); + const defStat = partyMember.getStat(Stat.DEF, false); + const spDefStat = partyMember.getStat(Stat.SPDEF, false); - expect(defValue.value / defStat).toBe(1); - expect(spDefValue.value / spDefStat).toBe(1); - }, 20000); + expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(defStat); + expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(spDefStat); + }, TIMEOUT); + + it("should not provide a boost for Gigantamax Pokémon", async() => { + game.override.starterForms({ + [Species.PIKACHU]: 8, + [Species.EEVEE]: 2, + [Species.DURALUDON]: 1, + [Species.MEOWTH]: 1 + }); + + const gMaxablePokemon = [ Species.PIKACHU, Species.EEVEE, Species.DURALUDON, Species.MEOWTH ]; + + await game.classicMode.startBattle([ + Utils.randItem(gMaxablePokemon) + ]); + + const partyMember = game.scene.getPlayerPokemon()!; + + vi.spyOn(partyMember, "getEffectiveStat").mockImplementation((stat, _opponent?, _move?, _isCritical?) => { + const statValue = new Utils.NumberHolder(partyMember.getStat(stat, false)); + game.scene.applyModifiers(StatBoosterModifier, partyMember.isPlayer(), partyMember, stat, statValue); + + // Ignore other calculations for simplicity + + return Math.floor(statValue.value); + }); + + const defStat = partyMember.getStat(Stat.DEF, false); + const spDefStat = partyMember.getStat(Stat.SPDEF, false); + + expect(partyMember.getEffectiveStat(Stat.DEF)).toBe(defStat); + expect(partyMember.getEffectiveStat(Stat.SPDEF)).toBe(spDefStat); + }, TIMEOUT); }); From d4cd74c8b7106f11ab0518de12b656253937c270 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:58:21 -0700 Subject: [PATCH 06/16] [P2 Bug] Baddy Bad shouldn't activate Reflect if the target uses Protect, make gravity and water/mud sport ignore protect(#4180) --- src/data/move.ts | 5 +++- src/test/moves/baddy_bad.test.ts | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/test/moves/baddy_bad.test.ts diff --git a/src/data/move.ts b/src/data/move.ts index 7800d6df12a..bf61ed5befe 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4747,7 +4747,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { return false; } - if (move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) { + if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) { user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY); return true; } @@ -7417,6 +7417,7 @@ export function initMoves() { .attr(HighCritAttr) .attr(StatusEffectAttr, StatusEffect.BURN), new StatusMove(Moves.MUD_SPORT, Type.GROUND, -1, 15, -1, 0, 3) + .ignoresProtect() .attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5) .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.ICE_BALL, Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 3) @@ -7541,6 +7542,7 @@ export function initMoves() { .recklessMove(), new AttackMove(Moves.MAGICAL_LEAF, Type.GRASS, MoveCategory.SPECIAL, 60, -1, 20, -1, 0, 3), new StatusMove(Moves.WATER_SPORT, Type.WATER, -1, 15, -1, 0, 3) + .ignoresProtect() .attr(AddArenaTagAttr, ArenaTagType.WATER_SPORT, 5) .target(MoveTarget.BOTH_SIDES), new SelfStatusMove(Moves.CALM_MIND, Type.PSYCHIC, -1, 20, -1, 0, 3) @@ -7569,6 +7571,7 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.ROOSTED, true, false) .triageMove(), new StatusMove(Moves.GRAVITY, Type.PSYCHIC, -1, 5, -1, 0, 4) + .ignoresProtect() .attr(AddArenaTagAttr, ArenaTagType.GRAVITY, 5) .target(MoveTarget.BOTH_SIDES), new StatusMove(Moves.MIRACLE_EYE, Type.PSYCHIC, -1, 40, -1, 0, 4) diff --git a/src/test/moves/baddy_bad.test.ts b/src/test/moves/baddy_bad.test.ts new file mode 100644 index 00000000000..d1a221453a6 --- /dev/null +++ b/src/test/moves/baddy_bad.test.ts @@ -0,0 +1,43 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Baddy Bad", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const TIMEOUT = 20 * 1000; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([Moves.SPLASH]) + .battleType("single") + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH) + .ability(Abilities.BALL_FETCH); + }); + + it("should not activate Reflect if the move fails due to Protect", async () => { + game.override.enemyMoveset(Moves.PROTECT); + await game.classicMode.startBattle([Species.FEEBAS]); + + game.move.select(Moves.BADDY_BAD); + await game.phaseInterceptor.to("BerryPhase"); + + expect(game.scene.arena.tags.length).toBe(0); + }, TIMEOUT); +}); From fec218b747ba7fd685d9dbd54d381884c2743c31 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:59:57 -0700 Subject: [PATCH 07/16] [Refactor] `setTypeIcons` explicitly handles `null`, mark it as such (#4155) --- src/ui/starter-select-ui-handler.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 0c3d8de61b0..d99c25bc612 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -28,15 +28,15 @@ import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; import { Egg } from "#app/data/egg"; import Overrides from "#app/overrides"; -import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; -import {Passive as PassiveAttr} from "#enums/passive"; +import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; +import { Passive as PassiveAttr } from "#enums/passive"; import * as Challenge from "../data/challenge"; import MoveInfoOverlay from "./move-info-overlay"; import { getEggTierForSpecies } from "#app/data/egg"; import { Device } from "#enums/devices"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import { EggSourceType } from "#app/enums/egg-source-types"; import AwaitableUiHandler from "./awaitable-ui-handler"; import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "./dropdown"; @@ -2905,7 +2905,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } const speciesForm = getPokemonSpeciesForm(species.speciesId, props.formIndex); - this.setTypeIcons(speciesForm.type1, speciesForm!.type2!); // TODO: are those bangs correct? + this.setTypeIcons(speciesForm.type1, speciesForm.type2); this.pokemonSprite.clearTint(); if (this.pokerusSpecies.includes(species)) { @@ -3242,13 +3242,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonFormText.setText(formText ? i18next.t(`pokemonForm:${speciesName}${formText}`) : ""); } - this.setTypeIcons(speciesForm.type1, speciesForm.type2!); // TODO: is this bang correct? + this.setTypeIcons(speciesForm.type1, speciesForm.type2); } else { this.pokemonAbilityText.setText(""); this.pokemonPassiveText.setText(""); this.pokemonNatureText.setText(""); - // @ts-ignore - this.setTypeIcons(null, null); // TODO: resolve ts-ignore.. huh!? + this.setTypeIcons(null, null); } } else { this.shinyOverlay.setVisible(false); @@ -3258,8 +3257,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonAbilityText.setText(""); this.pokemonPassiveText.setText(""); this.pokemonNatureText.setText(""); - // @ts-ignore - this.setTypeIcons(null, null); // TODO: resolve ts-ignore.. huh!? + this.setTypeIcons(null, null); } if (!this.starterMoveset) { @@ -3292,7 +3290,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.updateInstructions(); } - setTypeIcons(type1: Type, type2: Type): void { + setTypeIcons(type1: Type | null, type2: Type | null): void { if (type1 !== null) { this.type1Icon.setVisible(true); this.type1Icon.setFrame(Type[type1].toLowerCase()); From f294f034aa1c7ac41b67a7f4ce7374ad2fb051db Mon Sep 17 00:00:00 2001 From: Mumble <171087428+frutescens@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:00:26 -0700 Subject: [PATCH 08/16] [Bug] Run History displays Pokemon that have their natures changed during the run (#4149) * Nature mints... spaghetti... * Update src/ui/run-info-ui-handler.ts Co-authored-by: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com> * No effect when no items --------- Co-authored-by: frutescens Co-authored-by: MokaStitcher <54149968+MokaStitcher@users.noreply.github.com> --- src/ui/run-info-ui-handler.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index f398abed6f5..b7ad5f5adec 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -541,7 +541,9 @@ export default class RunInfoUiHandler extends UiHandler { // Contains Name, Level + Nature, Ability, Passive const pokeInfoTextContainer = this.scene.add.container(-85, 3.5); const textContainerFontSize = "34px"; - const pNature = getNatureName(pokemon.nature); + // This checks if the Pokemon's nature has been overwritten during the run and displays the change accurately + const pNature = pokemon.getNature(); + const pNatureName = getNatureName(pNature); const pName = pokemon.getNameToRender(); //With the exception of Korean/Traditional Chinese/Simplified Chinese, the code shortens the terms for ability and passive to their first letter. //These languages are exempted because they are already short enough. @@ -557,7 +559,7 @@ export default class RunInfoUiHandler extends UiHandler { // Japanese is set to a greater line spacing of 35px in addBBCodeTextObject() if lineSpacing < 12. const lineSpacing = (i18next.resolvedLanguage === "ja") ? 12 : 3; const pokeInfoText = addBBCodeTextObject(this.scene, 0, 0, pName, TextStyle.SUMMARY, {fontSize: textContainerFontSize, lineSpacing: lineSpacing}); - pokeInfoText.appendText(`${i18next.t("saveSlotSelectUiHandler:lv")}${Utils.formatFancyLargeNumber(pokemon.level, 1)} - ${pNature}`); + pokeInfoText.appendText(`${i18next.t("saveSlotSelectUiHandler:lv")}${Utils.formatFancyLargeNumber(pokemon.level, 1)} - ${pNatureName}`); pokeInfoText.appendText(pAbilityInfo); pokeInfoText.appendText(pPassiveInfo); pokeInfoTextContainer.add(pokeInfoText); @@ -568,7 +570,7 @@ export default class RunInfoUiHandler extends UiHandler { const pStats : string[]= []; pokemon.stats.forEach((element) => pStats.push(Utils.formatFancyLargeNumber(element, 1))); for (let i = 0; i < pStats.length; i++) { - const isMult = getNatureStatMultiplier(pokemon.nature, i); + const isMult = getNatureStatMultiplier(pNature, i); pStats[i] = (isMult < 1) ? pStats[i] + "[color=#40c8f8]↓[/color]" : pStats[i]; pStats[i] = (isMult > 1) ? pStats[i] + "[color=#f89890]↑[/color]" : pStats[i]; } @@ -889,10 +891,12 @@ export default class RunInfoUiHandler extends UiHandler { } break; case Button.CYCLE_ABILITY: - if (this.partyVisibility) { - this.showParty(false); - } else { - this.showParty(true); + if (this.runInfo.modifiers.length !== 0) { + if (this.partyVisibility) { + this.showParty(false); + } else { + this.showParty(true); + } } break; } From 18dc1029b789050011950bbb2246eb9e8c0e6bb8 Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:01:16 -0700 Subject: [PATCH 09/16] [Misc] Update issue/feature template (#4148) * simplify bug-report form. Add `Triage` label to bug & feature form * Add repro textfield to bug form * Fix typo --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yml | 67 +++++----------------- .github/ISSUE_TEMPLATE/feature_request.yml | 2 +- 2 files changed, 16 insertions(+), 53 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 23c4a0a2159..eb270dc8f80 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,7 +1,7 @@ name: Bug Report description: Create a report to help us improve title: "[Bug] " -labels: ["Bug"] +labels: ["Bug", "Triage"] body: - type: markdown attributes: @@ -19,21 +19,12 @@ body: value: | --- - type: textarea - id: session-file + id: repro attributes: - label: Session export file - description: Open Menu → ManageData → Export Session → Select slot. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)). - placeholder: Focus me and then drop your file here (or use the upload button at the bottom) + label: Reproduction + description: Describe the steps to reproduce this bug. If applicable attach user/session data at the bottom validations: - required: false - - type: textarea - id: data-file - attributes: - label: User data export file - description: Open Menu → ManageData → Export Data. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)). - placeholder: Focus me and then drop your file here (or use the upload button at the bottom) - validations: - required: false + required: true - type: markdown attributes: value: | @@ -60,48 +51,20 @@ body: attributes: value: | --- - - type: dropdown - id: os + - type: textarea + id: session-file attributes: - label: What OS did you observe the bug on? - multiple: true - options: - - PC/Windows - - Mac/OSX - - Linux - - iOS - - Android - - Other - validations: - required: true - - type: input - id: os-other - attributes: - label: If other please specify + label: Session export file + description: Open Menu → ManageData → Export Session → Select slot. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)). + placeholder: Focus me and then drop your file here (or use the upload button at the bottom) validations: required: false - - type: markdown + - type: textarea + id: data-file attributes: - value: | - --- - - type: dropdown - id: browser - attributes: - label: Which browser do you use? - multiple: true - options: - - Chrome - - Firefox - - Safari - - Edge - - Opera - - Other - validations: - required: true - - type: input - id: browser-other - attributes: - label: If other please specify + label: User data export file + description: Open Menu → ManageData → Export Data. The file should now be in your `/Downloads` directory. Change the file extension type from `.prsv` to `.txt` (How to [Windows](https://www.guidingtech.com/how-to-change-file-type-on-windows/) | [Mac](https://support.apple.com/guide/mac-help/show-or-hide-filename-extensions-on-mac-mchlp2304/mac) | [iOS](https://www.guidingtech.com/change-file-type-extension-on-iphone/)). + placeholder: Focus me and then drop your file here (or use the upload button at the bottom) validations: required: false - type: markdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 843f7feab59..29a79b38158 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,7 +1,7 @@ name: Feature Request description: Suggest an idea for this project title: "[Feature] " -labels: ["Enhancement"] +labels: ["Enhancement", "Triage"] body: - type: markdown attributes: From 951b5685904949aa002eda36271747b43272d710 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:05:43 -0700 Subject: [PATCH 10/16] [Documentation] Add some tsdocs to `move.ts`, mark rollout and iceball (P) (#4099) * Add some tsdocs to `move.ts`, some misc cleanup * Mark Rollout and Ice Ball as partial --- src/data/move.ts | 93 ++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index bf61ed5befe..135122311ff 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -81,6 +81,16 @@ export enum MoveFlags { MAKES_CONTACT = 1 << 0, IGNORE_PROTECT = 1 << 1, IGNORE_VIRTUAL = 1 << 2, + /** + * Sound-based moves have the following effects: + * - Pokemon with the {@linkcode Abilities.SOUNDPROOF Soundproof Ability} are unaffected by other Pokemon's sound-based moves. + * - Pokemon affected by {@linkcode Moves.THROAT_CHOP Throat Chop} cannot use sound-based moves for two turns. + * - Sound-based moves used by a Pokemon with {@linkcode Abilities.LIQUID_VOICE Liquid Voice} become Water-type moves. + * - Sound-based moves used by a Pokemon with {@linkcode Abilities.PUNK_ROCK Punk Rock} are boosted by 30%. Pokemon with Punk Rock also take half damage from sound-based moves. + * - All sound-based moves (except Howl) can hit Pokemon behind an active {@linkcode Moves.SUBSTITUTE Substitute}. + * + * cf https://bulbapedia.bulbagarden.net/wiki/Sound-based_move + */ SOUND_BASED = 1 << 3, HIDE_USER = 1 << 4, HIDE_TARGET = 1 << 5, @@ -93,19 +103,20 @@ export enum MoveFlags { * @see {@linkcode Move.recklessMove()} */ RECKLESS_MOVE = 1 << 10, + /** Indicates a move should be affected by {@linkcode Abilities.BULLETPROOF} */ BALLBOMB_MOVE = 1 << 11, + /** Grass types and pokemon with {@linkcode Abilities.OVERCOAT} are immune to powder moves */ POWDER_MOVE = 1 << 12, + /** Indicates a move should trigger {@linkcode Abilities.DANCER} */ DANCE_MOVE = 1 << 13, + /** Indicates a move should trigger {@linkcode Abilities.WIND_RIDER} */ WIND_MOVE = 1 << 14, + /** Indicates a move should trigger {@linkcode Abilities.TRIAGE} */ TRIAGE_MOVE = 1 << 15, IGNORE_ABILITIES = 1 << 16, - /** - * Enables all hits of a multi-hit move to be accuracy checked individually - */ + /** Enables all hits of a multi-hit move to be accuracy checked individually */ CHECK_ALL_HITS = 1 << 17, - /** - * Indicates a move is able to be redirected to allies in a double battle if the attacker faints - */ + /** Indicates a move is able to be redirected to allies in a double battle if the attacker faints */ REDIRECT_COUNTER = 1 << 18, } @@ -118,22 +129,22 @@ export default class Move implements Localizable { private _type: Type; private _category: MoveCategory; public moveTarget: MoveTarget; - public power: integer; - public accuracy: integer; - public pp: integer; + public power: number; + public accuracy: number; + public pp: number; public effect: string; - public chance: integer; - public priority: integer; - public generation: integer; - public attrs: MoveAttr[]; - private conditions: MoveCondition[]; - private flags: integer; - private nameAppend: string; + /** The chance of a move's secondary effects activating */ + public chance: number; + public priority: number; + public generation: number; + public attrs: MoveAttr[] = []; + private conditions: MoveCondition[] = []; + /** The move's {@linkcode MoveFlags} */ + private flags: number = 0; + private nameAppend: string = ""; - constructor(id: Moves, type: Type, category: MoveCategory, defaultMoveTarget: MoveTarget, power: integer, accuracy: integer, pp: integer, chance: integer, priority: integer, generation: integer) { + constructor(id: Moves, type: Type, category: MoveCategory, defaultMoveTarget: MoveTarget, power: number, accuracy: number, pp: number, chance: number, priority: number, generation: number) { this.id = id; - - this.nameAppend = ""; this._type = type; this._category = category; this.moveTarget = defaultMoveTarget; @@ -144,10 +155,6 @@ export default class Move implements Localizable { this.priority = priority; this.generation = generation; - this.attrs = []; - this.conditions = []; - - this.flags = 0; if (defaultMoveTarget === MoveTarget.USER) { this.setFlag(MoveFlags.IGNORE_PROTECT, true); } @@ -377,7 +384,7 @@ export default class Move implements Localizable { * @param makesContact The value (boolean) to set the flag to * @returns The {@linkcode Move} that called this function */ - makesContact(makesContact: boolean = true): this { // TODO: is true the correct default? + makesContact(makesContact: boolean = true): this { this.setFlag(MoveFlags.MAKES_CONTACT, makesContact); return this; } @@ -388,7 +395,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.CURSE} * @returns The {@linkcode Move} that called this function */ - ignoresProtect(ignoresProtect: boolean = true): this { // TODO: is `true` the correct default? + ignoresProtect(ignoresProtect: boolean = true): this { this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect); return this; } @@ -399,7 +406,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.NATURE_POWER} * @returns The {@linkcode Move} that called this function */ - ignoresVirtual(ignoresVirtual: boolean = true): this { // TODO: is `true` the correct default? + ignoresVirtual(ignoresVirtual: boolean = true): this { this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual); return this; } @@ -410,7 +417,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.UPROAR} * @returns The {@linkcode Move} that called this function */ - soundBased(soundBased: boolean = true): this { // TODO: is `true` the correct default? + soundBased(soundBased: boolean = true): this { this.setFlag(MoveFlags.SOUND_BASED, soundBased); return this; } @@ -421,7 +428,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.TELEPORT} * @returns The {@linkcode Move} that called this function */ - hidesUser(hidesUser: boolean = true): this { // TODO: is `true` the correct default? + hidesUser(hidesUser: boolean = true): this { this.setFlag(MoveFlags.HIDE_USER, hidesUser); return this; } @@ -432,7 +439,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.WHIRLWIND} * @returns The {@linkcode Move} that called this function */ - hidesTarget(hidesTarget: boolean = true): this { // TODO: is `true` the correct default? + hidesTarget(hidesTarget: boolean = true): this { this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget); return this; } @@ -443,7 +450,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.BITE} * @returns The {@linkcode Move} that called this function */ - bitingMove(bitingMove: boolean = true): this { // TODO: is `true` the correct default? + bitingMove(bitingMove: boolean = true): this { this.setFlag(MoveFlags.BITING_MOVE, bitingMove); return this; } @@ -454,7 +461,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.WATER_PULSE} * @returns The {@linkcode Move} that called this function */ - pulseMove(pulseMove: boolean = true): this { // TODO: is `true` the correct default? + pulseMove(pulseMove: boolean = true): this { this.setFlag(MoveFlags.PULSE_MOVE, pulseMove); return this; } @@ -465,7 +472,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.DRAIN_PUNCH} * @returns The {@linkcode Move} that called this function */ - punchingMove(punchingMove: boolean = true): this { // TODO: is `true` the correct default? + punchingMove(punchingMove: boolean = true): this { this.setFlag(MoveFlags.PUNCHING_MOVE, punchingMove); return this; } @@ -476,7 +483,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.X_SCISSOR} * @returns The {@linkcode Move} that called this function */ - slicingMove(slicingMove: boolean = true): this { // TODO: is `true` the correct default? + slicingMove(slicingMove: boolean = true): this { this.setFlag(MoveFlags.SLICING_MOVE, slicingMove); return this; } @@ -487,7 +494,7 @@ export default class Move implements Localizable { * @param recklessMove The value to set the flag to * @returns The {@linkcode Move} that called this function */ - recklessMove(recklessMove: boolean = true): this { // TODO: is `true` the correct default? + recklessMove(recklessMove: boolean = true): this { this.setFlag(MoveFlags.RECKLESS_MOVE, recklessMove); return this; } @@ -498,7 +505,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.ELECTRO_BALL} * @returns The {@linkcode Move} that called this function */ - ballBombMove(ballBombMove: boolean = true): this { // TODO: is `true` the correct default? + ballBombMove(ballBombMove: boolean = true): this { this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove); return this; } @@ -509,7 +516,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.STUN_SPORE} * @returns The {@linkcode Move} that called this function */ - powderMove(powderMove: boolean = true): this { // TODO: is `true` the correct default? + powderMove(powderMove: boolean = true): this { this.setFlag(MoveFlags.POWDER_MOVE, powderMove); return this; } @@ -520,7 +527,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.PETAL_DANCE} * @returns The {@linkcode Move} that called this function */ - danceMove(danceMove: boolean = true): this { // TODO: is `true` the correct default? + danceMove(danceMove: boolean = true): this { this.setFlag(MoveFlags.DANCE_MOVE, danceMove); return this; } @@ -531,7 +538,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.HURRICANE} * @returns The {@linkcode Move} that called this function */ - windMove(windMove: boolean = true): this { // TODO: is `true` the correct default? + windMove(windMove: boolean = true): this { this.setFlag(MoveFlags.WIND_MOVE, windMove); return this; } @@ -542,7 +549,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.ABSORB} * @returns The {@linkcode Move} that called this function */ - triageMove(triageMove: boolean = true): this { // TODO: is `true` the correct default? + triageMove(triageMove: boolean = true): this { this.setFlag(MoveFlags.TRIAGE_MOVE, triageMove); return this; } @@ -553,7 +560,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.SUNSTEEL_STRIKE} * @returns The {@linkcode Move} that called this function */ - ignoresAbilities(ignoresAbilities: boolean = true): this { // TODO: is `true` the correct default? + ignoresAbilities(ignoresAbilities: boolean = true): this { this.setFlag(MoveFlags.IGNORE_ABILITIES, ignoresAbilities); return this; } @@ -564,7 +571,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.TRIPLE_AXEL} * @returns The {@linkcode Move} that called this function */ - checkAllHits(checkAllHits: boolean = true): this { // TODO: is `true` the correct default? + checkAllHits(checkAllHits: boolean = true): this { this.setFlag(MoveFlags.CHECK_ALL_HITS, checkAllHits); return this; } @@ -575,7 +582,7 @@ export default class Move implements Localizable { * example: @see {@linkcode Moves.METAL_BURST} * @returns The {@linkcode Move} that called this function */ - redirectCounter(redirectCounter: boolean = true): this { // TODO: is `true` the correct default? + redirectCounter(redirectCounter: boolean = true): this { this.setFlag(MoveFlags.REDIRECT_COUNTER, redirectCounter); return this; } @@ -7138,6 +7145,7 @@ export function initMoves() { new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2) .attr(StatStageChangeAttr, [ Stat.ATK ], -2), new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2) + .partial() .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL), new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2) .attr(SurviveDamageAttr), @@ -7421,6 +7429,7 @@ export function initMoves() { .attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5) .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.ICE_BALL, Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 3) + .partial() .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL) .ballBombMove(), new AttackMove(Moves.NEEDLE_ARM, Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, 30, 0, 3) From 91d266ea74eaba7f20cca88a17a666c92791ed80 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:31:38 -0700 Subject: [PATCH 11/16] [Bug] Burning Bulwark, King's Shield, Obstruct and Silk Trap no longer protect against status moves. (#4106) * Obstruct et al no longer protect against status moves * Remove `.js` from import Co-authored-by: ImperialSympathizer <110984302+ben-lear@users.noreply.github.com> * Add tsdocs for new/modified classes * List relevant moves in tsdocs --------- Co-authored-by: ImperialSympathizer <110984302+ben-lear@users.noreply.github.com> --- src/data/battler-tags.ts | 19 ++++++++- src/phases/move-effect-phase.ts | 5 ++- src/test/moves/obstruct.test.ts | 71 +++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 src/test/moves/obstruct.test.ts diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 52e039ed874..66b6676a4f5 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -1298,6 +1298,13 @@ export class ProtectedTag extends BattlerTag { } } +/** Base class for `BattlerTag`s that block damaging moves but not status moves */ +export class DamageProtectedTag extends ProtectedTag {} + +/** + * `BattlerTag` class for moves that block damaging moves damage the enemy if the enemy's move makes contact + * Used by {@linkcode Moves.SPIKY_SHIELD} + */ export class ContactDamageProtectedTag extends ProtectedTag { private damageRatio: number; @@ -1333,7 +1340,11 @@ export class ContactDamageProtectedTag extends ProtectedTag { } } -export class ContactStatStageChangeProtectedTag extends ProtectedTag { +/** + * `BattlerTag` class for moves that block damaging moves and lower enemy stats if the enemy's move makes contact + * Used by {@linkcode Moves.KINGS_SHIELD}, {@linkcode Moves.OBSTRUCT}, {@linkcode Moves.SILK_TRAP} + */ +export class ContactStatStageChangeProtectedTag extends DamageProtectedTag { private stat: BattleStat; private levels: number; @@ -1389,7 +1400,11 @@ export class ContactPoisonProtectedTag extends ProtectedTag { } } -export class ContactBurnProtectedTag extends ProtectedTag { +/** + * `BattlerTag` class for moves that block damaging moves and burn the enemy if the enemy's move makes contact + * Used by {@linkcode Moves.BURNING_BULWARK} + */ +export class ContactBurnProtectedTag extends DamageProtectedTag { constructor(sourceMove: Moves) { super(sourceMove, BattlerTagType.BURNING_BULWARK); } diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index fb2b82ada03..41fb03c4f4f 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -3,7 +3,7 @@ import { BattlerIndex } from "#app/battle"; import { applyPreAttackAbAttrs, AddSecondStrikeAbAttr, IgnoreMoveEffectsAbAttr, applyPostDefendAbAttrs, PostDefendAbAttr, applyPostAttackAbAttrs, PostAttackAbAttr, MaxMultiHitAbAttr, AlwaysHitAbAttr } from "#app/data/ability"; import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag"; import { MoveAnim } from "#app/data/battle-anims"; -import { BattlerTagLapseType, ProtectedTag, SemiInvulnerableTag } from "#app/data/battler-tags"; +import { BattlerTagLapseType, DamageProtectedTag, ProtectedTag, SemiInvulnerableTag } from "#app/data/battler-tags"; import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger, ChargeAttr, MoveCategory, NoEffectAttr, HitsTagAttr } from "#app/data/move"; import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms"; import { BattlerTagType } from "#app/enums/battler-tag-type"; @@ -152,7 +152,8 @@ export class MoveEffectPhase extends PokemonPhase { /** Is the target protected by Protect, etc. or a relevant conditional protection effect? */ const isProtected = (bypassIgnoreProtect.value || !this.move.getMove().checkFlag(MoveFlags.IGNORE_PROTECT, user, target)) - && (hasConditionalProtectApplied.value || target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType))); + && (hasConditionalProtectApplied.value || (!target.findTags(t => t instanceof DamageProtectedTag).length && target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType))) + || (this.move.getMove().category !== MoveCategory.STATUS && target.findTags(t => t instanceof DamageProtectedTag).find(t => target.lapseTag(t.tagType)))); /** Does this phase represent the invoked move's first strike? */ const firstHit = (user.turnData.hitsLeft === user.turnData.hitCount); diff --git a/src/test/moves/obstruct.test.ts b/src/test/moves/obstruct.test.ts new file mode 100644 index 00000000000..539b11090de --- /dev/null +++ b/src/test/moves/obstruct.test.ts @@ -0,0 +1,71 @@ +import { Moves } from "#app/enums/moves"; +import { Stat } from "#app/enums/stat"; +import { Abilities } from "#enums/abilities"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Obstruct", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const TIMEOUT = 20 * 1000; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleType("single") + .enemyAbility(Abilities.BALL_FETCH) + .ability(Abilities.BALL_FETCH) + .moveset([Moves.OBSTRUCT]); + }); + + it("protects from contact damaging moves and lowers the opponent's defense by 2 stages", async () => { + game.override.enemyMoveset(Array(4).fill(Moves.ICE_PUNCH)); + await game.classicMode.startBattle(); + + game.move.select(Moves.OBSTRUCT); + await game.phaseInterceptor.to("BerryPhase"); + + const player = game.scene.getPlayerPokemon()!; + const enemy = game.scene.getEnemyPokemon()!; + + expect(player.isFullHp()).toBe(true); + expect(enemy.getStatStage(Stat.DEF)).toBe(-2); + }, TIMEOUT); + + it("protects from non-contact damaging moves and doesn't lower the opponent's defense by 2 stages", async () => { + game.override.enemyMoveset(Array(4).fill(Moves.WATER_GUN)); + await game.classicMode.startBattle(); + + game.move.select(Moves.OBSTRUCT); + await game.phaseInterceptor.to("BerryPhase"); + + const player = game.scene.getPlayerPokemon()!; + const enemy = game.scene.getEnemyPokemon()!; + + expect(player.isFullHp()).toBe(true); + expect(enemy.getStatStage(Stat.DEF)).toBe(0); + }, TIMEOUT); + + it("doesn't protect from status moves", async () => { + game.override.enemyMoveset(Array(4).fill(Moves.GROWL)); + await game.classicMode.startBattle(); + + game.move.select(Moves.OBSTRUCT); + await game.phaseInterceptor.to("BerryPhase"); + + const player = game.scene.getPlayerPokemon()!; + + expect(player.getStatStage(Stat.ATK)).toBe(-1); + }, TIMEOUT); +}); From 8195373824118b0e76bf51de260ad77a4c82ddcd Mon Sep 17 00:00:00 2001 From: Lylian BALL <131535108+PyGaVS@users.noreply.github.com> Date: Thu, 12 Sep 2024 03:31:57 +0200 Subject: [PATCH 12/16] [Move] Add Retaliate double damage condition (#1831) * Add retaliate double damage condition * undo override changes * add death history and bug fix where retaliate didn't work after 10 turns * delete the unnecassary log * optimization * made some corrections * add retaliate test as draft * add retaliate test * Update src/test/moves/retaliate.test.ts (delete log) Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * remove submodule * Update src/test/moves/retaliate.test.ts Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> * update retaliate test * Update src/test/moves/retaliate.test.ts Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> * update unit test * remove wide lens for retaliate test * Update src/test/moves/retaliate.test.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update src/battle.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update src/test/moves/retaliate.test.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update src/test/moves/retaliate.test.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * optimization * Fix indentation * Use default values * Add parentheses for clarity * Update src/battle.ts Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> * Update src/battle.ts Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> * Update src/data/move.ts Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> * Update src/phases/faint-phase.ts Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> * Update src/phases/faint-phase.ts Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> * bug on import --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> --- src/battle.ts | 9 +++++- src/data/move.ts | 10 ++++++- src/phases/faint-phase.ts | 2 ++ src/test/moves/retaliate.test.ts | 49 ++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/test/moves/retaliate.test.ts diff --git a/src/battle.ts b/src/battle.ts index b80caa9e679..a3e7b0a4336 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -1,5 +1,4 @@ import BattleScene from "./battle-scene"; -import { EnemyPokemon, PlayerPokemon, QueuedMove } from "./field/pokemon"; import { Command } from "./ui/command-ui-handler"; import * as Utils from "./utils"; import Trainer, { TrainerVariant } from "./field/trainer"; @@ -7,6 +6,7 @@ import { GameMode } from "./game-mode"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; import { PokeballType } from "./data/pokeball"; import { trainerConfigs } from "#app/data/trainer-config"; +import Pokemon, { EnemyPokemon, PlayerPokemon, QueuedMove } from "#app/field/pokemon"; import { ArenaTagType } from "#enums/arena-tag-type"; import { BattleSpec } from "#enums/battle-spec"; import { Moves } from "#enums/moves"; @@ -38,6 +38,11 @@ export interface TurnCommand { args?: any[]; } +export interface FaintLogEntry { + pokemon: Pokemon, + turn: number +} + interface TurnCommands { [key: number]: TurnCommand | null } @@ -69,6 +74,8 @@ export default class Battle { public playerFaints: number = 0; /** The number of times a Pokemon on the enemy's side has fainted this battle */ public enemyFaints: number = 0; + public playerFaintsHistory: FaintLogEntry[] = []; + public enemyFaintsHistory: FaintLogEntry[] = []; private rngCounter: number = 0; diff --git a/src/data/move.ts b/src/data/move.ts index 135122311ff..9916ccc1c9f 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -8024,7 +8024,15 @@ export function initMoves() { new StatusMove(Moves.REFLECT_TYPE, Type.NORMAL, -1, 15, -1, 0, 5) .attr(CopyTypeAttr), new AttackMove(Moves.RETALIATE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 5, -1, 0, 5) - .partial(), + .attr(MovePowerMultiplierAttr, (user, target, move) => { + const turn = user.scene.currentBattle.turn; + const lastPlayerFaint = user.scene.currentBattle.playerFaintsHistory[user.scene.currentBattle.playerFaintsHistory.length - 1]; + const lastEnemyFaint = user.scene.currentBattle.enemyFaintsHistory[user.scene.currentBattle.enemyFaintsHistory.length - 1]; + return ( + (lastPlayerFaint !== undefined && turn - lastPlayerFaint.turn === 1 && user.isPlayer()) || + (lastEnemyFaint !== undefined && turn - lastEnemyFaint.turn === 1 && !user.isPlayer()) + ) ? 2 : 1; + }), new AttackMove(Moves.FINAL_GAMBIT, Type.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5) .attr(UserHpDamageAttr) .attr(SacrificialAttrOnHit), diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index c30003b79aa..169d667113a 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -55,8 +55,10 @@ export class FaintPhase extends PokemonPhase { // Track total times pokemon have been KO'd for supreme overlord/last respects if (pokemon.isPlayer()) { this.scene.currentBattle.playerFaints += 1; + this.scene.currentBattle.playerFaintsHistory.push({ pokemon: pokemon, turn: this.scene.currentBattle.turn }); } else { this.scene.currentBattle.enemyFaints += 1; + this.scene.currentBattle.enemyFaintsHistory.push({ pokemon: pokemon, turn: this.scene.currentBattle.turn }); } this.scene.queueMessage(i18next.t("battle:fainted", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), null, true); diff --git a/src/test/moves/retaliate.test.ts b/src/test/moves/retaliate.test.ts new file mode 100644 index 00000000000..62965fffba6 --- /dev/null +++ b/src/test/moves/retaliate.test.ts @@ -0,0 +1,49 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import { Species } from "#enums/species"; +import { Moves } from "#enums/moves"; +import { allMoves } from "#app/data/move"; + +describe("Moves - Retaliate", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + const retaliate = allMoves[Moves.RETALIATE]; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleType("single") + .enemySpecies(Species.SNORLAX) + .enemyMoveset([Moves.RETALIATE, Moves.RETALIATE, Moves.RETALIATE, Moves.RETALIATE]) + .enemyLevel(100) + .moveset([Moves.RETALIATE, Moves.SPLASH]) + .startingLevel(80) + .disableCrits(); + }); + + it("increases power if ally died previous turn", async () => { + vi.spyOn(retaliate, "calculateBattlePower"); + await game.startBattle([Species.ABRA, Species.COBALION]); + game.move.select(Moves.RETALIATE); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(retaliate.calculateBattlePower).toHaveLastReturnedWith(70); + game.doSelectPartyPokemon(1); + + await game.toNextTurn(); + game.move.select(Moves.RETALIATE); + await game.phaseInterceptor.to("MoveEffectPhase"); + expect(retaliate.calculateBattlePower).toHaveReturnedWith(140); + }); +}); From 6decd918e53bf93e397a1f1c22acd358ac9a17f1 Mon Sep 17 00:00:00 2001 From: Madmadness65 <59298170+Madmadness65@users.noreply.github.com> Date: Wed, 11 Sep 2024 20:47:41 -0500 Subject: [PATCH 13/16] [Enhancement] Implement Tera-based form changes (Ogerpon and Terapagos) (#4147) * Add Tera-based form changes * Make teraType property private --- src/data/pokemon-forms.ts | 126 ++++++++++++++++++++++++-------------- src/modifier/modifier.ts | 4 +- 2 files changed, 84 insertions(+), 46 deletions(-) diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 0d3e511bcba..20703cebe81 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -1,8 +1,9 @@ -import { PokemonFormChangeItemModifier } from "../modifier/modifier"; +import { PokemonFormChangeItemModifier, TerastallizeModifier } from "../modifier/modifier"; import Pokemon from "../field/pokemon"; import { SpeciesFormKey } from "./pokemon-species"; import { StatusEffect } from "./status-effect"; import { MoveCategory, allMoves } from "./move"; +import { Type } from "./type"; import { Constructor } from "#app/utils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; @@ -357,6 +358,41 @@ export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger { } } +/** + * Class used for triggering form changes based on the user's Tera type. + * Used by Ogerpon and Terapagos. + * @extends SpeciesFormChangeTrigger + */ +export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger { + /** The Tera type that triggers the form change */ + private teraType: Type; + + constructor(teraType: Type) { + super(); + this.teraType = teraType; + } + + /** + * Checks if the associated Pokémon has the required Tera Shard that matches with the associated Tera type. + * @param {Pokemon} pokemon the Pokémon that is trying to do the form change + * @returns `true` if the Pokémon can change forms, `false` otherwise + */ + canChange(pokemon: Pokemon): boolean { + return !!pokemon.scene.findModifier(m => m instanceof TerastallizeModifier && m.pokemonId === pokemon.id && m.teraType === this.teraType); + } +} + +/** + * Class used for triggering form changes based on the user's lapsed Tera type. + * Used by Ogerpon and Terapagos. + * @extends SpeciesFormChangeTrigger + */ +export class SpeciesFormChangeLapseTeraTrigger extends SpeciesFormChangeTrigger { + canChange(pokemon: Pokemon): boolean { + return !!pokemon.scene.findModifier(m => m instanceof TerastallizeModifier && m.pokemonId === pokemon.id); + } +} + /** * Class used for triggering form changes based on weather. * Used by Castform and Cherrim. @@ -592,6 +628,23 @@ export const pokemonFormChanges: PokemonFormChanges = { [Species.ALTARIA]: [ new SpeciesFormChange(Species.ALTARIA, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.ALTARIANITE)) ], + [Species.CASTFORM]: [ + new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), + new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), + new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), + new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), + new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), + new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), + new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), + new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), + new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), + new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), + new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), + new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), + new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeActiveTrigger(), true), + new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true), + new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true) + ], [Species.BANETTE]: [ new SpeciesFormChange(Species.BANETTE, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.BANETTITE)) ], @@ -627,6 +680,11 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.DEOXYS, "normal", "defense", new SpeciesFormChangeItemTrigger(FormChangeItem.HARD_METEORITE)), new SpeciesFormChange(Species.DEOXYS, "normal", "speed", new SpeciesFormChangeItemTrigger(FormChangeItem.SMOOTH_METEORITE)) ], + [Species.CHERRIM]: [ + new SpeciesFormChange(Species.CHERRIM, "overcast", "sunshine", new SpeciesFormChangeWeatherTrigger(Abilities.FLOWER_GIFT, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true), + new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FLOWER_GIFT, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG, WeatherType.HAIL, WeatherType.HEAVY_RAIN, WeatherType.SNOW, WeatherType.RAIN ]), true), + new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeActiveTrigger(), true) + ], [Species.LOPUNNY]: [ new SpeciesFormChange(Species.LOPUNNY, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.LOPUNNITE)) ], @@ -822,6 +880,14 @@ export const pokemonFormChanges: PokemonFormChanges = { [Species.SANDACONDA]: [ new SpeciesFormChange(Species.SANDACONDA, "", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], + [Species.CRAMORANT]: [ + new SpeciesFormChange(Species.CRAMORANT, "", "gulping", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() >= .5)), + new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)), + new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeManualTrigger, true), + new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeManualTrigger, true), + new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeActiveTrigger(false), true), + new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeActiveTrigger(false), true) + ], [Species.TOXTRICITY]: [ new SpeciesFormChange(Species.TOXTRICITY, "amped", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), new SpeciesFormChange(Species.TOXTRICITY, "lowkey", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), @@ -848,6 +914,10 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.ALCREMIE, "caramel-swirl", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)), new SpeciesFormChange(Species.ALCREMIE, "rainbow-swirl", SpeciesFormKey.GIGANTAMAX, new SpeciesFormChangeItemTrigger(FormChangeItem.MAX_MUSHROOMS)) ], + [Species.EISCUE]: [ + new SpeciesFormChange(Species.EISCUE, "", "no-ice", new SpeciesFormChangeManualTrigger(), true), + new SpeciesFormChange(Species.EISCUE, "no-ice", "", new SpeciesFormChangeManualTrigger(), true) + ], [Species.MORPEKO]: [ new SpeciesFormChange(Species.MORPEKO, "full-belly", "hangry", new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.MORPEKO, "hangry", "full-belly", new SpeciesFormChangeManualTrigger(), true) @@ -883,58 +953,24 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.OGERPON, "teal-mask", "wellspring-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.WELLSPRING_MASK)), new SpeciesFormChange(Species.OGERPON, "teal-mask", "hearthflame-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.HEARTHFLAME_MASK)), new SpeciesFormChange(Species.OGERPON, "teal-mask", "cornerstone-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.CORNERSTONE_MASK)), - new SpeciesFormChange(Species.OGERPON, "teal-mask", "teal-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Grass Tera Shard - new SpeciesFormChange(Species.OGERPON, "teal-mask-tera", "teal-mask", new SpeciesFormChangeManualTrigger(), true), //When no longer holding a Grass Tera Shard - new SpeciesFormChange(Species.OGERPON, "wellspring-mask", "wellspring-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Water Tera Shard - new SpeciesFormChange(Species.OGERPON, "wellspring-mask-tera", "wellspring-mask", new SpeciesFormChangeManualTrigger(), true), //When no longer holding a Water Tera Shard - new SpeciesFormChange(Species.OGERPON, "hearthflame-mask", "hearthflame-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Fire Tera Shard - new SpeciesFormChange(Species.OGERPON, "hearthflame-mask-tera", "hearthflame-mask", new SpeciesFormChangeManualTrigger(), true), //When no longer holding a Fire Tera Shard - new SpeciesFormChange(Species.OGERPON, "cornerstone-mask", "cornerstone-mask-tera", new SpeciesFormChangeManualTrigger(), true), //When holding a Rock Tera Shard - new SpeciesFormChange(Species.OGERPON, "cornerstone-mask-tera", "cornerstone-mask", new SpeciesFormChangeManualTrigger(), true) //When no longer holding a Rock Tera Shard + new SpeciesFormChange(Species.OGERPON, "teal-mask", "teal-mask-tera", new SpeciesFormChangeTeraTrigger(Type.GRASS)), + new SpeciesFormChange(Species.OGERPON, "teal-mask-tera", "teal-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.GRASS)), + new SpeciesFormChange(Species.OGERPON, "wellspring-mask", "wellspring-mask-tera", new SpeciesFormChangeTeraTrigger(Type.WATER)), + new SpeciesFormChange(Species.OGERPON, "wellspring-mask-tera", "wellspring-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.WATER)), + new SpeciesFormChange(Species.OGERPON, "hearthflame-mask", "hearthflame-mask-tera", new SpeciesFormChangeTeraTrigger(Type.FIRE)), + new SpeciesFormChange(Species.OGERPON, "hearthflame-mask-tera", "hearthflame-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.FIRE)), + new SpeciesFormChange(Species.OGERPON, "cornerstone-mask", "cornerstone-mask-tera", new SpeciesFormChangeTeraTrigger(Type.ROCK)), + new SpeciesFormChange(Species.OGERPON, "cornerstone-mask-tera", "cornerstone-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.ROCK)) ], [Species.TERAPAGOS]: [ new SpeciesFormChange(Species.TERAPAGOS, "", "terastal", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.TERAPAGOS, "terastal", "stellar", new SpeciesFormChangeManualTrigger(), true), //When holding a Stellar Tera Shard - new SpeciesFormChange(Species.TERAPAGOS, "stellar", "terastal", new SpeciesFormChangeManualTrigger(), true) //When no longer holding a Stellar Tera Shard + new SpeciesFormChange(Species.TERAPAGOS, "terastal", "stellar", new SpeciesFormChangeTeraTrigger(Type.STELLAR)), + new SpeciesFormChange(Species.TERAPAGOS, "stellar", "terastal", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.STELLAR)) ], [Species.GALAR_DARMANITAN]: [ new SpeciesFormChange(Species.GALAR_DARMANITAN, "", "zen", new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.GALAR_DARMANITAN, "zen", "", new SpeciesFormChangeManualTrigger(), true) ], - [Species.EISCUE]: [ - new SpeciesFormChange(Species.EISCUE, "", "no-ice", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.EISCUE, "no-ice", "", new SpeciesFormChangeManualTrigger(), true), - ], - [Species.CRAMORANT]: [ - new SpeciesFormChange(Species.CRAMORANT, "", "gulping", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() >= .5)), - new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)), - new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeManualTrigger, true), - new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeManualTrigger, true), - new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeActiveTrigger(false), true), - new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeActiveTrigger(false), true), - ], - [Species.CASTFORM]: [ - new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), - new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), - new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), - new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), - new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), - new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), - new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), - new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), - new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), - new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), - new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), - new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), - new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeActiveTrigger(), true), - new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true), - new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true), - ], - [Species.CHERRIM]: [ - new SpeciesFormChange(Species.CHERRIM, "overcast", "sunshine", new SpeciesFormChangeWeatherTrigger(Abilities.FLOWER_GIFT, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true), - new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FLOWER_GIFT, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG, WeatherType.HAIL, WeatherType.HEAVY_RAIN, WeatherType.SNOW, WeatherType.RAIN ]), true), - new SpeciesFormChange(Species.CHERRIM, "sunshine", "overcast", new SpeciesFormChangeActiveTrigger(), true), - ], }; export function initPokemonForms() { diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 9273eb42b90..14a5bac361f 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -15,7 +15,7 @@ import { BerryType } from "#enums/berry-type"; import { StatusEffect, getStatusEffectHealText } from "../data/status-effect"; import { achvs } from "../system/achv"; import { VoucherType } from "../system/voucher"; -import { FormChangeItem, SpeciesFormChangeItemTrigger } from "../data/pokemon-forms"; +import { FormChangeItem, SpeciesFormChangeItemTrigger, SpeciesFormChangeLapseTeraTrigger, SpeciesFormChangeTeraTrigger } from "../data/pokemon-forms"; import { Nature } from "#app/data/nature"; import Overrides from "#app/overrides"; import { ModifierType, modifierTypes } from "./modifier-type"; @@ -763,6 +763,7 @@ export class TerastallizeModifier extends LapsingPokemonHeldItemModifier { apply(args: any[]): boolean { const pokemon = args[0] as Pokemon; if (pokemon.isPlayer()) { + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeTeraTrigger); pokemon.scene.validateAchv(achvs.TERASTALLIZE); if (this.teraType === Type.STELLAR) { pokemon.scene.validateAchv(achvs.STELLAR_TERASTALLIZE); @@ -776,6 +777,7 @@ export class TerastallizeModifier extends LapsingPokemonHeldItemModifier { const ret = super.lapse(args); if (!ret) { const pokemon = args[0] as Pokemon; + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeLapseTeraTrigger); pokemon.updateSpritePipelineData(); } return ret; From 28012b8d859186219c4919a2f0b546f55e47aef2 Mon Sep 17 00:00:00 2001 From: schmidtc1 <62030095+schmidtc1@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:20:24 -0400 Subject: [PATCH 14/16] [Bug] Fixes Freezy Frost visual bug when attacking ally, and Freezy Frost not applying effects when fainting a target (#3753) * Resolves bugs with freezy frost vs ally, and freezy frost fainting opp * Adjusts unit tests, adds one more for doubles * Refactor apply function to follow the async/await pattern * Eslint fix attempt * Update freezy_frost.test.ts Remove js file extension --- src/data/move.ts | 16 ++--- src/test/moves/freezy_frost.test.ts | 103 ++++++++++++++++++++-------- 2 files changed, 81 insertions(+), 38 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 9916ccc1c9f..672a1154a0e 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2786,28 +2786,26 @@ export class ResetStatsAttr extends MoveEffectAttr { super(); this.targetAllPokemon = targetAllPokemon; } - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - if (!super.apply(user, target, move, args)) { - return false; - } - + async apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { + const promises: Promise[] = []; if (this.targetAllPokemon) { // Target all pokemon on the field when Freezy Frost or Haze are used const activePokemon = user.scene.getField(true); - activePokemon.forEach(p => this.resetStats(p)); + activePokemon.forEach(p => promises.push(this.resetStats(p))); target.scene.queueMessage(i18next.t("moveTriggers:statEliminated")); } else { // Affects only the single target when Clear Smog is used - this.resetStats(target); + promises.push(this.resetStats(target)); target.scene.queueMessage(i18next.t("moveTriggers:resetStats", {pokemonName: getPokemonNameWithAffix(target)})); } + await Promise.all(promises); return true; } - resetStats(pokemon: Pokemon) { + async resetStats(pokemon: Pokemon): Promise { for (const s of BATTLE_STATS) { pokemon.setStatStage(s, 0); } - pokemon.updateInfo(); + return pokemon.updateInfo(); } } diff --git a/src/test/moves/freezy_frost.test.ts b/src/test/moves/freezy_frost.test.ts index 05c61aab49a..ad5163dae48 100644 --- a/src/test/moves/freezy_frost.test.ts +++ b/src/test/moves/freezy_frost.test.ts @@ -1,12 +1,12 @@ import { Stat } from "#enums/stat"; -import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { allMoves } from "#app/data/move"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { CommandPhase } from "#app/phases/command-phase"; describe("Moves - Freezy Frost", () => { let phaserGame: Phaser.Game; @@ -23,38 +23,83 @@ describe("Moves - Freezy Frost", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.battleType("single"); + game.override + .battleType("single") + .enemySpecies(Species.RATTATA) + .enemyLevel(100) + .enemyMoveset([ Moves.HOWL, Moves.HOWL, Moves.HOWL, Moves.HOWL ]) + .enemyAbility(Abilities.BALL_FETCH) + .startingLevel(100) + .moveset([ Moves.FREEZY_FROST, Moves.HOWL, Moves.SPLASH ]) + .ability(Abilities.BALL_FETCH); - game.override.enemySpecies(Species.RATTATA); - game.override.enemyLevel(100); - game.override.enemyMoveset(Moves.SPLASH); - game.override.enemyAbility(Abilities.NONE); - - game.override.startingLevel(100); - game.override.moveset([Moves.FREEZY_FROST, Moves.SWORDS_DANCE, Moves.CHARM, Moves.SPLASH]); - vi.spyOn(allMoves[Moves.FREEZY_FROST], "accuracy", "get").mockReturnValue(100); - game.override.ability(Abilities.NONE); + vi.spyOn(allMoves[ Moves.FREEZY_FROST ], "accuracy", "get").mockReturnValue(100); }); - it("should clear all stat stage changes", { timeout: 10000 }, async () => { - await game.startBattle([Species.RATTATA]); - const user = game.scene.getPlayerPokemon()!; - const enemy = game.scene.getEnemyPokemon()!; + it( + "should clear stat changes of user and opponent", + async () => { + await game.classicMode.startBattle([ Species.SHUCKLE ]); + const user = game.scene.getPlayerPokemon()!; + const enemy = game.scene.getEnemyPokemon()!; - expect(user.getStatStage(Stat.ATK)).toBe(0); - expect(enemy.getStatStage(Stat.ATK)).toBe(0); + game.move.select(Moves.HOWL); + await game.toNextTurn(); - game.move.select(Moves.SWORDS_DANCE); - await game.phaseInterceptor.to(TurnInitPhase); + expect(user.getStatStage(Stat.ATK)).toBe(1); + expect(enemy.getStatStage(Stat.ATK)).toBe(1); - game.move.select(Moves.CHARM); - await game.phaseInterceptor.to(TurnInitPhase); - expect(user.getStatStage(Stat.ATK)).toBe(2); - expect(enemy.getStatStage(Stat.ATK)).toBe(-2); + game.move.select(Moves.FREEZY_FROST); + await game.toNextTurn(); - game.move.select(Moves.FREEZY_FROST); - await game.phaseInterceptor.to(TurnInitPhase); - expect(user.getStatStage(Stat.ATK)).toBe(0); - expect(enemy.getStatStage(Stat.ATK)).toBe(0); - }); + expect(user.getStatStage(Stat.ATK)).toBe(0); + expect(enemy.getStatStage(Stat.ATK)).toBe(0); + }); + + it( + "should clear all stat changes even when enemy uses the move", + async () => { + game.override.enemyMoveset([ Moves.FREEZY_FROST, Moves.FREEZY_FROST, Moves.FREEZY_FROST, Moves.FREEZY_FROST ]); + await game.classicMode.startBattle([ Species.SHUCKLE ]); // Shuckle for slower Howl on first turn so Freezy Frost doesn't affect it. + const user = game.scene.getPlayerPokemon()!; + + game.move.select(Moves.HOWL); + await game.toNextTurn(); + + const userAtkBefore = user.getStatStage(Stat.ATK); + expect(userAtkBefore).toBe(1); + + game.move.select(Moves.SPLASH); + await game.toNextTurn(); + expect(user.getStatStage(Stat.ATK)).toBe(0); + }); + + it( + "should clear all stat changes in double battle", + async () => { + game.override.battleType("double"); + await game.classicMode.startBattle([ Species.SHUCKLE, Species.RATTATA ]); + const [ leftPlayer, rightPlayer ] = game.scene.getPlayerField(); + const [ leftOpp, rightOpp ] = game.scene.getEnemyField(); + + game.move.select(Moves.HOWL, 0); + await game.phaseInterceptor.to(CommandPhase); + game.move.select(Moves.SPLASH, 1); + await game.toNextTurn(); + + expect(leftPlayer.getStatStage(Stat.ATK)).toBe(1); + expect(rightPlayer.getStatStage(Stat.ATK)).toBe(1); + expect(leftOpp.getStatStage(Stat.ATK)).toBe(2); // Both enemies use Howl + expect(rightOpp.getStatStage(Stat.ATK)).toBe(2); + + game.move.select(Moves.FREEZY_FROST, 0, leftOpp.getBattlerIndex()); + await game.phaseInterceptor.to(CommandPhase); + game.move.select(Moves.SPLASH, 1); + await game.toNextTurn(); + + expect(leftPlayer.getStatStage(Stat.ATK)).toBe(0); + expect(rightPlayer.getStatStage(Stat.ATK)).toBe(0); + expect(leftOpp.getStatStage(Stat.ATK)).toBe(0); + expect(rightOpp.getStatStage(Stat.ATK)).toBe(0); + }); }); From 7ed7fec8086ad1d52f7b6d7c273b0fbf9d129d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20T=2E?= <99520451+Vassiat@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:12:20 -0400 Subject: [PATCH 15/16] [BUG][UI/UX] Correction of errors when ``` Save & Quit``` and ``` Log out``` (#3105) * Fixes confirmation issues in SAVE_AND_QUIT and LOG_OUT * Added LOADING mode to prevent spamming from SAVE_AND_QUIT and LOG_OUT buttons, and added option to set black background for LOADING mode * Fixed conditional statement to ensure robustness in live environments to avoid potential issues in production * Good overlay position --- src/ui/menu-ui-handler.ts | 40 ++++++++++++++++++++++++++++---------- src/ui/modal-ui-handler.ts | 19 ++++++++++++++++++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index adbb3089e5c..b8c3cfd1364 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -460,6 +460,7 @@ export default class MenuUiHandler extends MessageUiHandler { } } } + this.showText("", 0); switch (adjustedCursor) { case MenuOptions.GAME_SETTINGS: ui.setOverlayMode(Mode.SETTINGS); @@ -548,15 +549,28 @@ export default class MenuUiHandler extends MessageUiHandler { case MenuOptions.SAVE_AND_QUIT: if (this.scene.currentBattle) { success = true; + const doSaveQuit = () => { + ui.setMode(Mode.LOADING, { + buttonActions: [], fadeOut: () => + this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => { + + this.scene.reset(true); + }) + }); + }; if (this.scene.currentBattle.turn > 1) { ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { - ui.setOverlayMode(Mode.CONFIRM, () => this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => this.scene.reset(true)), () => { + if (!this.active) { + this.showText("", 0); + return; + } + ui.setOverlayMode(Mode.CONFIRM, doSaveQuit, () => { ui.revertMode(); - ui.showText("", 0); + this.showText("", 0); }, false, -98); }); } else { - this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => this.scene.reset(true)); + doSaveQuit(); } } else { error = true; @@ -565,19 +579,25 @@ export default class MenuUiHandler extends MessageUiHandler { case MenuOptions.LOG_OUT: success = true; const doLogout = () => { - Utils.apiFetch("account/logout", true).then(res => { - if (!res.ok) { - console.error(`Log out failed (${res.status}: ${res.statusText})`); - } - Utils.removeCookie(Utils.sessionIdKey); - updateUserInfo().then(() => this.scene.reset(true, true)); + ui.setMode(Mode.LOADING, { + buttonActions: [], fadeOut: () => Utils.apiFetch("account/logout", true).then(res => { + if (!res.ok) { + console.error(`Log out failed (${res.status}: ${res.statusText})`); + } + Utils.removeCookie(Utils.sessionIdKey); + updateUserInfo().then(() => this.scene.reset(true, true)); + }) }); }; if (this.scene.currentBattle) { ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { + if (!this.active) { + this.showText("", 0); + return; + } ui.setOverlayMode(Mode.CONFIRM, doLogout, () => { ui.revertMode(); - ui.showText("", 0); + this.showText("", 0); }, false, -98); }); } else { diff --git a/src/ui/modal-ui-handler.ts b/src/ui/modal-ui-handler.ts index 5f586ec8db7..2aeafa68b23 100644 --- a/src/ui/modal-ui-handler.ts +++ b/src/ui/modal-ui-handler.ts @@ -89,6 +89,25 @@ export abstract class ModalUiHandler extends UiHandler { show(args: any[]): boolean { if (args.length >= 1 && "buttonActions" in args[0]) { super.show(args); + if (args[0].hasOwnProperty("fadeOut") && typeof args[0].fadeOut === "function") { + const [ marginTop, marginRight, marginBottom, marginLeft ] = this.getMargin(); + + const overlay = this.scene.add.rectangle(( this.getWidth() + marginLeft + marginRight) / 2, (this.getHeight() + marginTop + marginBottom) / 2,this.scene.game.canvas.width / 6,this.scene.game.canvas.height /6, 0); + overlay.setOrigin(0.5,0.5); + overlay.setName("rect-ui-overlay-modal"); + overlay.setAlpha(0); + + this.modalContainer.add(overlay); + this.modalContainer.moveTo(overlay,0); + + this.scene.tweens.add({ + targets: overlay, + alpha: 1, + duration: 250, + ease: "Sine.easeOut", + onComplete: args[0].fadeOut + }); + } const config = args[0] as ModalConfig; From 0af59bbb14d9d0b3d2b0a661e0a76c5a7e41189f Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Thu, 12 Sep 2024 00:13:57 -0400 Subject: [PATCH 16/16] [Refactor] Fix linter issue (#4191) --- src/ui/modal-ui-handler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/modal-ui-handler.ts b/src/ui/modal-ui-handler.ts index 2aeafa68b23..80a39d7bf7f 100644 --- a/src/ui/modal-ui-handler.ts +++ b/src/ui/modal-ui-handler.ts @@ -92,13 +92,13 @@ export abstract class ModalUiHandler extends UiHandler { if (args[0].hasOwnProperty("fadeOut") && typeof args[0].fadeOut === "function") { const [ marginTop, marginRight, marginBottom, marginLeft ] = this.getMargin(); - const overlay = this.scene.add.rectangle(( this.getWidth() + marginLeft + marginRight) / 2, (this.getHeight() + marginTop + marginBottom) / 2,this.scene.game.canvas.width / 6,this.scene.game.canvas.height /6, 0); - overlay.setOrigin(0.5,0.5); + const overlay = this.scene.add.rectangle(( this.getWidth() + marginLeft + marginRight) / 2, (this.getHeight() + marginTop + marginBottom) / 2, this.scene.game.canvas.width / 6, this.scene.game.canvas.height /6, 0); + overlay.setOrigin(0.5, 0.5); overlay.setName("rect-ui-overlay-modal"); overlay.setAlpha(0); this.modalContainer.add(overlay); - this.modalContainer.moveTo(overlay,0); + this.modalContainer.moveTo(overlay, 0); this.scene.tweens.add({ targets: overlay,