From 7a418109c3063d45cd0f334ff1ef61dc87f339c6 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 18:17:12 -0400 Subject: [PATCH 01/28] Fix not checking move conditions for AI --- src/data/ability.ts | 6 +++--- src/data/move.ts | 24 +++++++++++++++--------- src/field/pokemon.ts | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 35f6da685eb..7c350f025be 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -919,8 +919,8 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { private condition: PokemonAttackCondition; private powerMultiplier: number; - constructor(condition: PokemonAttackCondition, powerMultiplier: number) { - super(true); + constructor(condition: PokemonAttackCondition, powerMultiplier: number, showAbility: boolean = true) { + super(showAbility); this.condition = condition; this.powerMultiplier = powerMultiplier; } @@ -2725,7 +2725,7 @@ export function initAbilities() { .attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPD, 1) .ignorable(), new Ability(Abilities.RIVALRY, 4) - .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender === target.gender, 1.25) + .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender === target.gender, 1.25, true) .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75), new Ability(Abilities.STEADFAST, 4) .attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1), diff --git a/src/data/move.ts b/src/data/move.ts index a13c1ac8861..d6367794a35 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3645,6 +3645,20 @@ export class MoneyAttr extends MoveEffectAttr { } } +export class LastResortAttr extends MoveAttr { + getCondition(): MoveConditionFunc { + return (user: Pokemon, target: Pokemon, move: Move) => { + const uniqueUsedMoveIds = new Set(); + const movesetMoveIds = user.getMoveset().map(m => m.moveId); + user.getMoveHistory().map(m => { + if (m.move !== move.id && movesetMoveIds.find(mm => mm === m.move)) + uniqueUsedMoveIds.add(m.move); + }); + return uniqueUsedMoveIds.size >= movesetMoveIds.length - 1; + }; + } +} + const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY); const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune(); @@ -4836,15 +4850,7 @@ export function initMoves() { new AttackMove(Moves.PUNISHMENT, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4) .unimplemented(), new AttackMove(Moves.LAST_RESORT, Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, 0, 4) - .condition((user, target, move) => { - const uniqueUsedMoveIds = new Set(); - const movesetMoveIds = user.getMoveset().map(m => m.moveId); - user.getMoveHistory().map(m => { - if (m.move !== move.id && movesetMoveIds.find(mm => mm === m.move)) - uniqueUsedMoveIds.add(m.move); - }); - return uniqueUsedMoveIds.size >= movesetMoveIds.length - 1; - }), + .attr(LastResortAttr), new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4) .attr(AbilityChangeAttr, Abilities.INSOMNIA), new AttackMove(Moves.SUCKER_PUNCH, Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, 1, 4) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 82915ce41bc..ce2d8dfffe6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2680,7 +2680,7 @@ export class EnemyPokemon extends Pokemon { for (let mt of moveTargets[move.id]) { const target = this.scene.getField()[mt]; let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); - if (move.name.endsWith(' (N)')) + if (move.name.endsWith(' (N)') || !move.applyConditions(this, target, move)) targetScore = -20; else if (move instanceof AttackMove) { const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove); From 89e2642d91e419d2ec61574f98d1e9286f213ce9 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 18:24:21 -0400 Subject: [PATCH 02/28] Fix update issue for battle stats display --- src/ui/battle-info.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index ae8f518e727..2ca0457c801 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -498,11 +498,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.lastLevel = pokemon.level; } - if (pokemon.summonData) { - const battleStats = pokemon.summonData.battleStats.join(''); - - if (this.lastBattleStats !== battleStats) - this.updateBattleStats(pokemon.summonData.battleStats); + const battleStats = pokemon.summonData + ? pokemon.summonData.battleStats + : battleStatOrder.map(() => 0); + const battleStatsStr = battleStats.join(''); + + if (this.lastBattleStats !== battleStatsStr) { + this.updateBattleStats(battleStats); + this.lastBattleStats = battleStatsStr; } this.shinyIcon.setVisible(pokemon.isShiny()); From e34b20466426a9944a71306b993c6d149eeabd20 Mon Sep 17 00:00:00 2001 From: TeKrop Date: Wed, 1 May 2024 22:48:58 +0200 Subject: [PATCH 03/28] feat: added support for localisation on battle scene sentences --- src/field/pokemon.ts | 13 +++++++------ src/locales/de/menu.ts | 7 ++++++- src/locales/en/menu.ts | 7 ++++++- src/locales/es/menu.ts | 7 ++++++- src/locales/fr/menu.ts | 7 ++++++- src/locales/it/menu.ts | 7 ++++++- 6 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index ce2d8dfffe6..8c9224f5e1f 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -45,6 +45,7 @@ import { TerrainType } from '../data/terrain'; import { TrainerSlot } from '../data/trainer-config'; import { BerryType } from '../data/berry'; import { ABILITY_OVERRIDE, MOVE_OVERRIDE, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides'; +import i18next from '../plugins/i18n'; export enum FieldPosition { CENTER, @@ -1417,7 +1418,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo); this.turnData.damageTaken += damage.value; if (isCritical) - this.scene.queueMessage('A critical hit!'); + this.scene.queueMessage(i18next.t('menu:hitResultCriticalHit')); this.scene.setPhaseQueueSplice(); if (source.isPlayer()) { this.scene.validateAchvs(DamageAchv, damage); @@ -1435,16 +1436,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (source.turnData.hitsLeft === 1) { switch (result) { case HitResult.SUPER_EFFECTIVE: - this.scene.queueMessage('It\'s super effective!'); + this.scene.queueMessage(i18next.t('menu:hitResultSuperEffective')); break; case HitResult.NOT_VERY_EFFECTIVE: - this.scene.queueMessage('It\'s not very effective…'); + this.scene.queueMessage(i18next.t('menu:hitResultNotVeryEffective')); break; case HitResult.NO_EFFECT: - this.scene.queueMessage(`It doesn\'t affect ${this.name}!`); + this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); break; case HitResult.ONE_HIT_KO: - this.scene.queueMessage('It\'s a one-hit KO!'); + this.scene.queueMessage(i18next.t('menu:hitResultOneHitKO')); break; } } @@ -1461,7 +1462,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier)); } if (!typeMultiplier.value) - this.scene.queueMessage(`It doesn\'t affect ${this.name}!`); + this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS; break; } diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index 442cfae218f..a8e0a901f3f 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -63,5 +63,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 82a09e49d4f..21620e9b30f 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -82,5 +82,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 5dccc2e4eb3..0a43f19b768 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -66,5 +66,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index d5478c67a26..c485412bf1a 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -77,5 +77,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", "loading": "Chargement…", - "playersOnline": "Joueurs Connectés" + "playersOnline": "Joueurs Connectés", + "hitResultCriticalHit": "Coup critique!", + "hitResultSuperEffective": "C'est super efficace!", + "hitResultNotVeryEffective": "Ce n'est pas très efficace…", + "hitResultNoEffect": "Ça n'affecte pas {{pokemonName}}…", + "hitResultOneHitKO": "K.O. en un coup!" } as const; diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index c37a37b5169..118c1dccb5f 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -11,5 +11,10 @@ export const menu: SimpleTranslationEntries = { "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online" + "playersOnline": "Players Online", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!" } as const; \ No newline at end of file From 6ac224ab8a4e3e5ec6aa7fdc2d8b60111343f2fd Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 18:53:48 -0400 Subject: [PATCH 04/28] Refactor to split battle messages from menu --- src/field/pokemon.ts | 12 ++--- src/locales/de/battle.ts | 52 ++++++++++++++++++ src/locales/de/fight-ui-handler.ts | 6 +++ src/locales/de/menu.ts | 31 +---------- src/locales/en/battle.ts | 52 ++++++++++++++++++ src/locales/en/menu.ts | 50 +---------------- src/locales/es/battle.ts | 52 ++++++++++++++++++ src/locales/es/fight-ui-handler.ts | 6 +++ src/locales/es/menu.ts | 50 +---------------- src/locales/fr/battle.ts | 52 ++++++++++++++++++ src/locales/fr/menu.ts | 50 +---------------- src/locales/it/battle.ts | 52 ++++++++++++++++++ src/locales/it/fight-ui-handler.ts | 6 +++ src/locales/it/menu.ts | 35 +++++++++--- src/phases.ts | 86 +++++++++++++++--------------- src/plugins/i18n.ts | 18 +++++++ 16 files changed, 378 insertions(+), 232 deletions(-) create mode 100644 src/locales/de/battle.ts create mode 100644 src/locales/de/fight-ui-handler.ts create mode 100644 src/locales/en/battle.ts create mode 100644 src/locales/es/battle.ts create mode 100644 src/locales/es/fight-ui-handler.ts create mode 100644 src/locales/fr/battle.ts create mode 100644 src/locales/it/battle.ts create mode 100644 src/locales/it/fight-ui-handler.ts diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 8c9224f5e1f..a966a24303f 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1418,7 +1418,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo); this.turnData.damageTaken += damage.value; if (isCritical) - this.scene.queueMessage(i18next.t('menu:hitResultCriticalHit')); + this.scene.queueMessage(i18next.t('battle:hitResultCriticalHit')); this.scene.setPhaseQueueSplice(); if (source.isPlayer()) { this.scene.validateAchvs(DamageAchv, damage); @@ -1436,16 +1436,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (source.turnData.hitsLeft === 1) { switch (result) { case HitResult.SUPER_EFFECTIVE: - this.scene.queueMessage(i18next.t('menu:hitResultSuperEffective')); + this.scene.queueMessage(i18next.t('battle:hitResultSuperEffective')); break; case HitResult.NOT_VERY_EFFECTIVE: - this.scene.queueMessage(i18next.t('menu:hitResultNotVeryEffective')); + this.scene.queueMessage(i18next.t('battle:hitResultNotVeryEffective')); break; case HitResult.NO_EFFECT: - this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); + this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name })); break; case HitResult.ONE_HIT_KO: - this.scene.queueMessage(i18next.t('menu:hitResultOneHitKO')); + this.scene.queueMessage(i18next.t('battle:hitResultOneHitKO')); break; } } @@ -1462,7 +1462,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier)); } if (!typeMultiplier.value) - this.scene.queueMessage(i18next.t('menu:hitResultNoEffect', { pokemonName: this.name })); + this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name })); result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS; break; } diff --git a/src/locales/de/battle.ts b/src/locales/de/battle.ts new file mode 100644 index 00000000000..61191a1165a --- /dev/null +++ b/src/locales/de/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "{{bossName}} erscheint.", + "trainerAppeared": "{{trainerName}}\nmöchte kämpfen!", + "singleWildAppeared": "Ein wildes {{pokemonName}} erscheint!", + "multiWildAppeared": "Ein wildes {{pokemonName1}}\nund {{pokemonName2}} erscheinen!", + "playerComeBack": "Komm zurück, {{pokemonName}}!", + "trainerComeBack": "{{trainerName}} ruft {{pokemonName}} zurück!", + "playerGo": "Los! {{pokemonName}}!", + "trainerGo": "{{trainerName}} sendet {{pokemonName}} raus!", + "switchQuestion": "Willst du\n{{pokemonName}} auswechseln?", + "trainerDefeated": `You defeated\n{{trainerName}}!`, + "pokemonCaught": "{{pokemonName}} was caught!", + "pokemon": "Pokémon", + "sendOutPokemon": "Los! {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "But it failed!", + "attackHitsCount": `Hit {{count}} time(s)!`, + "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", + "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", + "learnMove": "{{pokemonName}} learned\n{{moveName}}!", + "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", + "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", + "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", + "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", + "learnMoveForgetQuestion": "Which move should be forgotten?", + "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", + "levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!", + "moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.", + "moveDisabled": "{{moveName}} ist deaktiviert!", + "noPokeballForce": "Eine unsichtbare Kraft\nverhindert die Nutzung von Pokébällen.", + "noPokeballTrainer": "Du kannst das Pokémon\neines anderen Trainers nicht fangen!", + "noPokeballMulti": "Du kannst erst einen Pokéball werden,\nwenn nur noch ein Pokémon übrig ist!", + "noPokeballStrong": "Das Ziel-Pokémon ist zu stark, um gefangen zu werden!\nDu musst es zuerst schwächen!", + "noEscapeForce": "Eine unsichtbare Kraft\nverhindert die Flucht.", + "noEscapeTrainer": "Du kannst nicht\naus einem Trainerkampf fliehen!", + "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nverhindert {{escapeVerb}}!", + "runAwaySuccess": "You got away safely!", + "runAwayCannotEscape": 'You can\'t escape!', + "escapeVerbSwitch": "auswechseln", + "escapeVerbFlee": "flucht", + "notDisabled": "{{moveName}} ist\nnicht mehr deaktiviert!", + "skipItemQuestion": "Are you sure you want to skip taking an item?", + "eggHatching": "Oh?", + "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/de/fight-ui-handler.ts b/src/locales/de/fight-ui-handler.ts new file mode 100644 index 00000000000..1ce9e0317bf --- /dev/null +++ b/src/locales/de/fight-ui-handler.ts @@ -0,0 +1,6 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const fightUiHandler: SimpleTranslationEntries = { + "pp": "PP", + "power": "POWER", +} as const; \ No newline at end of file diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index a8e0a901f3f..c648b15bfe8 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -35,38 +35,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Bist du ein Junge oder ein Mädchen?", "boy": "Junge", "girl": "Mädchen", - "bossAppeared": "{{bossName}} erscheint.", - "trainerAppeared": "{{trainerName}}\nmöchte kämpfen!", - "singleWildAppeared": "Ein wildes {{pokemonName}} erscheint!", - "multiWildAppeared": "Ein wildes {{pokemonName1}}\nund {{pokemonName2}} erscheinen!", - "playerComeBack": "Komm zurück, {{pokemonName}}!", - "trainerComeBack": "{{trainerName}} ruft {{pokemonName}} zurück!", - "playerGo": "Los! {{pokemonName}}!", - "trainerGo": "{{trainerName}} sendet {{pokemonName}} raus!", - "switchQuestion": "Willst du\n{{pokemonName}} auswechseln?", - "pokemon": "Pokémon", - "sendOutPokemon": "Los! {{pokemonName}}!", - "levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!", - "moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.", - "moveDisabled": "{{moveName}} ist deaktiviert!", - "noPokeballForce": "Eine unsichtbare Kraft\nverhindert die Nutzung von Pokébällen.", - "noPokeballTrainer": "Du kannst das Pokémon\neines anderen Trainers nicht fangen!", - "noPokeballMulti": "Du kannst erst einen Pokéball werden,\nwenn nur noch ein Pokémon übrig ist!", - "noPokeballStrong": "Das Ziel-Pokémon ist zu stark, um gefangen zu werden!\nDu musst es zuerst schwächen!", - "noEscapeForce": "Eine unsichtbare Kraft\nverhindert die Flucht.", - "noEscapeTrainer": "Du kannst nicht\naus einem Trainerkampf fliehen!", - "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nverhindert {{escapeVerb}}!", - "escapeVerbSwitch": "auswechseln", - "escapeVerbFlee": "flucht", - "notDisabled": "{{moveName}} ist\nnicht mehr deaktiviert!", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/locales/en/battle.ts b/src/locales/en/battle.ts new file mode 100644 index 00000000000..599672a1b19 --- /dev/null +++ b/src/locales/en/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "{{bossName}} appeared.", + "trainerAppeared": "{{trainerName}}\nwould like to battle!", + "singleWildAppeared": "A wild {{pokemonName}} appeared!", + "multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!", + "playerComeBack": "Come back, {{pokemonName}}!", + "trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!", + "playerGo": "Go! {{pokemonName}}!", + "trainerGo": "{{trainerName}} sent out {{pokemonName}}!", + "switchQuestion": "Will you switch\n{{pokemonName}}?", + "trainerDefeated": `You defeated\n{{trainerName}}!`, + "pokemonCaught": "{{pokemonName}} was caught!", + "pokemon": "Pokémon", + "sendOutPokemon": "Go! {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "But it failed!", + "attackHitsCount": `Hit {{count}} time(s)!`, + "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", + "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", + "learnMove": "{{pokemonName}} learned\n{{moveName}}!", + "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", + "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", + "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", + "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", + "learnMoveForgetQuestion": "Which move should be forgotten?", + "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", + "levelCapUp": "The level cap\nhas increased to {{levelCap}}!", + "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", + "moveDisabled": "{{moveName}} is disabled!", + "noPokeballForce": "An unseen force\nprevents using Poké Balls.", + "noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!", + "noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!", + "noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!", + "noEscapeForce": "An unseen force\nprevents escape.", + "noEscapeTrainer": "You can't run\nfrom a trainer battle!", + "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!", + "runAwaySuccess": "You got away safely!", + "runAwayCannotEscape": 'You can\'t escape!', + "escapeVerbSwitch": "switching", + "escapeVerbFlee": "fleeing", + "notDisabled": "{{moveName}} is disabled\nno more!", + "skipItemQuestion": "Are you sure you want to skip taking an item?", + "eggHatching": "Oh?", + "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 21620e9b30f..42888b17337 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -35,57 +35,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Are you a boy or a girl?", "boy": "Boy", "girl": "Girl", - "bossAppeared": "{{bossName}} appeared.", - "trainerAppeared": "{{trainerName}}\nwould like to battle!", - "singleWildAppeared": "A wild {{pokemonName}} appeared!", - "multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!", - "playerComeBack": "Come back, {{pokemonName}}!", - "trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!", - "playerGo": "Go! {{pokemonName}}!", - "trainerGo": "{{trainerName}} sent out {{pokemonName}}!", - "switchQuestion": "Will you switch\n{{pokemonName}}?", - "trainerDefeated": `You defeated\n{{trainerName}}!`, - "pokemonCaught": "{{pokemonName}} was caught!", - "pokemon": "Pokémon", - "sendOutPokemon": "Go! {{pokemonName}}!", - "attackFailed": "But it failed!", - "attackHitsCount": `Hit {{count}} time(s)!`, - "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", - "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", - "learnMove": "{{pokemonName}} learned\n{{moveName}}!", - "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", - "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", - "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", - "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", - "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", - "learnMoveForgetQuestion": "Which move should be forgotten?", - "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", - "levelCapUp": "The level cap\nhas increased to {{levelCap}}!", - "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", - "moveDisabled": "{{moveName}} is disabled!", - "noPokeballForce": "An unseen force\nprevents using Poké Balls.", - "noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!", - "noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!", - "noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!", - "noEscapeForce": "An unseen force\nprevents escape.", - "noEscapeTrainer": "You can't run\nfrom a trainer battle!", - "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!", - "runAwaySuccess": "You got away safely!", - "runAwayCannotEscape": 'You can\'t escape!', - "escapeVerbSwitch": "switching", - "escapeVerbFlee": "fleeing", - "notDisabled": "{{moveName}} is disabled\nno more!", - "skipItemQuestion": "Are you sure you want to skip taking an item?", - "eggHatching": "Oh?", - "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/locales/es/battle.ts b/src/locales/es/battle.ts new file mode 100644 index 00000000000..1d4345a6f5b --- /dev/null +++ b/src/locales/es/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "¡{{bossName}} te corta el paso!", + "trainerAppeared": "¡{{trainerName}}\nte desafía!", + "singleWildAppeared": "¡Un {{pokemonName}} salvaje te corta el paso!", + "multiWildAppeared": "¡Un {{pokemonName1}} y un {{pokemonName2}} salvajes\nte cortan el paso!", + "playerComeBack": "¡{{pokemonName}}, ven aquí!", + "trainerComeBack": "¡{{trainerName}} retira a {{pokemonName}} del combate!", + "playerGo": "¡Adelante, {{pokemonName}}!", + "trainerGo": "¡{{trainerName}} saca a {{pokemonName}}!", + "switchQuestion": "¿Quieres cambiar a\n{{pokemonName}}?", + "trainerDefeated": "¡Has derrotado a\n{{trainerName}}!", + "pokemonCaught": "¡{{pokemonName}} atrapado!", + "pokemon": "Pokémon", + "sendOutPokemon": "¡Adelante, {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "¡Pero ha fallado!", + "attackHitsCount": `N.º de golpes: {{count}}.`, + "expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.", + "levelUp": "¡{{pokemonName}} ha subido al \nNv. {{level}}!", + "learnMove": "¡{{pokemonName}} ha aprendido {{moveName}}!", + "learnMovePrompt": "{{pokemonName}} quiere aprender {{moveName}}.", + "learnMoveLimitReached": "Pero, {{pokemonName}} ya conoce\ncuatro movimientos.", + "learnMoveReplaceQuestion": "¿Quieres sustituir uno de sus movimientos por {{moveName}}?", + "learnMoveStopTeaching": "¿Prefieres que no aprenda\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} no ha aprendido {{moveName}}.", + "learnMoveForgetQuestion": "¿Qué movimiento quieres que olvide?", + "learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.", + "levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!", + "moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.", + "moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!", + "noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.", + "noPokeballTrainer": "¡No puedes atrapar a los\nPokémon de los demás!", + "noPokeballMulti": "¡No se pueden lanzar Poké Balls\ncuando hay más de un Pokémon!", + "noPokeballStrong": "¡Este Pokémon es demasiado fuerte para ser capturado!\nNecesitas bajarle los PS primero!", + "noEscapeForce": "Una fuerza misteriosa\nte impide huir.", + "noEscapeTrainer": "¡No puedes huir de los\ncombates contra Entrenadores!", + "noEscapePokemon": "¡El movimiento {{moveName}} de {{pokemonName}} impide la huida!", + "runAwaySuccess": "¡Escapas sin problemas!", + "runAwayCannotEscape": "¡No has podido escapar!", + "escapeVerbSwitch": "cambiar", + "escapeVerbFlee": "huir", + "notDisabled": "¡El movimiento {{moveName}}\nya no está anulado!", + "skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?", + "eggHatching": "¿Y esto?", + "ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts new file mode 100644 index 00000000000..1ce9e0317bf --- /dev/null +++ b/src/locales/es/fight-ui-handler.ts @@ -0,0 +1,6 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const fightUiHandler: SimpleTranslationEntries = { + "pp": "PP", + "power": "POWER", +} as const; \ No newline at end of file diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 0a43f19b768..c67287ae0cc 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -19,57 +19,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "¿Eres un chico o una chica?", "boy": "Chico", "girl": "Chica", - "bossAppeared": "¡{{bossName}} te corta el paso!", - "trainerAppeared": "¡{{trainerName}}\nte desafía!", - "singleWildAppeared": "¡Un {{pokemonName}} salvaje te corta el paso!", - "multiWildAppeared": "¡Un {{pokemonName1}} y un {{pokemonName2}} salvajes\nte cortan el paso!", - "playerComeBack": "¡{{pokemonName}}, ven aquí!", - "trainerComeBack": "¡{{trainerName}} retira a {{pokemonName}} del combate!", - "playerGo": "¡Adelante, {{pokemonName}}!", - "trainerGo": "¡{{trainerName}} saca a {{pokemonName}}!", - "switchQuestion": "¿Quieres cambiar a\n{{pokemonName}}?", - "trainerDefeated": "¡Has derrotado a\n{{trainerName}}!", - "pokemonCaught": "¡{{pokemonName}} atrapado!", - "pokemon": "Pokémon", - "sendOutPokemon": "¡Adelante, {{pokemonName}}!", - "attackFailed": "¡Pero ha fallado!", - "attackHitsCount": `N.º de golpes: {{count}}.`, - "expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.", - "levelUp": "¡{{pokemonName}} ha subido al \nNv. {{level}}!", - "learnMove": "¡{{pokemonName}} ha aprendido {{moveName}}!", - "learnMovePrompt": "{{pokemonName}} quiere aprender {{moveName}}.", - "learnMoveLimitReached": "Pero, {{pokemonName}} ya conoce\ncuatro movimientos.", - "learnMoveReplaceQuestion": "¿Quieres sustituir uno de sus movimientos por {{moveName}}?", - "learnMoveStopTeaching": "¿Prefieres que no aprenda\n{{moveName}}?", - "learnMoveNotLearned": "{{pokemonName}} no ha aprendido {{moveName}}.", - "learnMoveForgetQuestion": "¿Qué movimiento quieres que olvide?", - "learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.", - "levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!", - "moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.", - "moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!", - "noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.", - "noPokeballTrainer": "¡No puedes atrapar a los\nPokémon de los demás!", - "noPokeballMulti": "¡No se pueden lanzar Poké Balls\ncuando hay más de un Pokémon!", - "noPokeballStrong": "¡Este Pokémon es demasiado fuerte para ser capturado!\nNecesitas bajarle los PS primero!", - "noEscapeForce": "Una fuerza misteriosa\nte impide huir.", - "noEscapeTrainer": "¡No puedes huir de los\ncombates contra Entrenadores!", - "noEscapePokemon": "¡El movimiento {{moveName}} de {{pokemonName}} impide la huida!", - "runAwaySuccess": "¡Escapas sin problemas!", - "runAwayCannotEscape": "¡No has podido escapar!", - "escapeVerbSwitch": "cambiar", - "escapeVerbFlee": "huir", - "notDisabled": "¡El movimiento {{moveName}}\nya no está anulado!", - "skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?", - "eggHatching": "¿Y esto?", - "ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/locales/fr/battle.ts b/src/locales/fr/battle.ts new file mode 100644 index 00000000000..8768c30155a --- /dev/null +++ b/src/locales/fr/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "Un {{bossName}} apparaît.", + "trainerAppeared": "Un combat est lancé\npar {{trainerName}} !", + "singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !", + "multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !", + "playerComeBack": "{{pokemonName}}, on change !\nReviens !", + "trainerComeBack": "{{trainerName}} retire {{pokemonName}} !", + "playerGo": "{{pokemonName}} ! Go !", + "trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !", + "switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?", + "trainerDefeated": `Vous avez battu\n{{trainerName}} !`, + "pokemonCaught": "Vous avez attrapé {{pokemonName}} !", + "pokemon": "Pokémon", + "sendOutPokemon": "{{pokemonName}} ! Go !", + "hitResultCriticalHit": "Coup critique!", + "hitResultSuperEffective": "C’est super efficace!", + "hitResultNotVeryEffective": "Ce n’est pas très efficace…", + "hitResultNoEffect": "Ça n’affecte pas {{pokemonName}}…", + "hitResultOneHitKO": "K.O. en un coup!", + "attackFailed": "Mais cela échoue !", + "attackHitsCount": `Touché {{count}} fois !`, + "expGain": "{{pokemonName}} gagne\n{{exp}} Points d’Exp !", + "levelUp": "{{pokemonName}} monte au\nN. {{level}} !", + "learnMove": "{{pokemonName}} apprend \n{{moveName}} !", + "learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.", + "learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.", + "learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?", + "learnMoveStopTeaching": "Arrêter d’apprendre\n{{moveName}} ?", + "learnMoveNotLearned": "{{pokemonName}} n’a pas appris\n{{moveName}}.", + "learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?", + "learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.", + "levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !", + "moveNotImplemented": "{{moveName}} n’est pas encore implémenté et ne peut pas être sélectionné.", + "moveDisabled": "{{moveName}} est sous entrave !", + "noPokeballForce": "Une force mystérieuse\nempêche l’utilisation des Poké Balls.", + "noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, c’est mal !", + "noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon!", + "noPokeballStrong": "Le Pokémon est trop fort pour être capturé !\nVous devez d’abord l’affaiblir !", + "noEscapeForce": "Une force mystérieuse\nempêche la fuite.", + "noEscapeTrainer": "On ne s’enfuit pas d’un\ncombat de Dresseurs !", + "noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !", + "runAwaySuccess": "Vous prenez la fuite !", + "runAwayCannotEscape": "Fuite impossible !", + "escapeVerbSwitch": "le changement", + "escapeVerbFlee": "la fuite", + "notDisabled": "{{moveName}} n’est plus sous entrave !", + "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre d’objet ?", + "eggHatching": "Oh ?", + "ivScannerUseQuestion": "Utiliser le Scanner d’IV sur {{pokemonName}} ?" +} as const; \ No newline at end of file diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index c485412bf1a..1744297089c 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -30,57 +30,9 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Es-tu un garçon ou une fille ?", "boy": "Garçon", "girl": "Fille", - "bossAppeared": "Un {{bossName}} apparaît.", - "trainerAppeared": "Un combat est lancé\npar {{trainerName}} !", - "singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !", - "multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !", - "playerComeBack": "{{pokemonName}}, on change !\nReviens !", - "trainerComeBack": "{{trainerName}} retire {{pokemonName}} !", - "playerGo": "{{pokemonName}} ! Go !", - "trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !", - "switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?", - "trainerDefeated": `Vous avez battu\n{{trainerName}} !`, - "pokemonCaught": "Vous avez attrapé {{pokemonName}} !", - "pokemon": "Pokémon", - "sendOutPokemon": "{{pokemonName}} ! Go !", - "attackFailed": "Mais cela échoue !", - "attackHitsCount": `Touché {{count}} fois !`, - "expGain": "{{pokemonName}} gagne\n{{exp}} Points d’Exp !", - "levelUp": "{{pokemonName}} monte au\nN. {{level}} !", - "learnMove": "{{pokemonName}} apprend \n{{moveName}} !", - "learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.", - "learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.", - "learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?", - "learnMoveStopTeaching": "Arrêter d’apprendre\n{{moveName}} ?", - "learnMoveNotLearned": "{{pokemonName}} n’a pas appris\n{{moveName}}.", - "learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?", - "learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.", - "levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !", - "moveNotImplemented": "{{moveName}} n’est pas encore implémenté et ne peut pas être sélectionné.", - "moveDisabled": "{{moveName}} est sous entrave !", - "noPokeballForce": "Une force mystérieuse\nempêche l’utilisation des Poké Balls.", - "noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, c’est mal !", - "noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon!", - "noPokeballStrong": "Le Pokémon est trop fort pour être capturé !\nVous devez d’abord l’affaiblir !", - "noEscapeForce": "Une force mystérieuse\nempêche la fuite.", - "noEscapeTrainer": "On ne s’enfuit pas d’un\ncombat de Dresseurs !", - "noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !", - "runAwaySuccess": "Vous prenez la fuite !", - "runAwayCannotEscape": "Fuite impossible !", - "escapeVerbSwitch": "le changement", - "escapeVerbFlee": "la fuite", - "notDisabled": "{{moveName}} n’est plus sous entrave !", - "skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre d’objet ?", - "eggHatching": "Oh ?", - "ivScannerUseQuestion": "Utiliser le Scanner d’IV sur {{pokemonName}} ?", "dailyRankings": "Classement du Jour", "weeklyRankings": "Classement de la Semaine", "noRankings": "Pas de Classement", "loading": "Chargement…", - "playersOnline": "Joueurs Connectés", - "hitResultCriticalHit": "Coup critique!", - "hitResultSuperEffective": "C'est super efficace!", - "hitResultNotVeryEffective": "Ce n'est pas très efficace…", - "hitResultNoEffect": "Ça n'affecte pas {{pokemonName}}…", - "hitResultOneHitKO": "K.O. en un coup!" + "playersOnline": "Joueurs Connectés" } as const; diff --git a/src/locales/it/battle.ts b/src/locales/it/battle.ts new file mode 100644 index 00000000000..599672a1b19 --- /dev/null +++ b/src/locales/it/battle.ts @@ -0,0 +1,52 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const battle: SimpleTranslationEntries = { + "bossAppeared": "{{bossName}} appeared.", + "trainerAppeared": "{{trainerName}}\nwould like to battle!", + "singleWildAppeared": "A wild {{pokemonName}} appeared!", + "multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!", + "playerComeBack": "Come back, {{pokemonName}}!", + "trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!", + "playerGo": "Go! {{pokemonName}}!", + "trainerGo": "{{trainerName}} sent out {{pokemonName}}!", + "switchQuestion": "Will you switch\n{{pokemonName}}?", + "trainerDefeated": `You defeated\n{{trainerName}}!`, + "pokemonCaught": "{{pokemonName}} was caught!", + "pokemon": "Pokémon", + "sendOutPokemon": "Go! {{pokemonName}}!", + "hitResultCriticalHit": "A critical hit!", + "hitResultSuperEffective": "It's super effective!", + "hitResultNotVeryEffective": "It's not very effective…", + "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", + "hitResultOneHitKO": "It's a one-hit KO!", + "attackFailed": "But it failed!", + "attackHitsCount": `Hit {{count}} time(s)!`, + "expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!", + "levelUp": "{{pokemonName}} grew to\nLv. {{level}}!", + "learnMove": "{{pokemonName}} learned\n{{moveName}}!", + "learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.", + "learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.", + "learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?", + "learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?", + "learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.", + "learnMoveForgetQuestion": "Which move should be forgotten?", + "learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.", + "levelCapUp": "The level cap\nhas increased to {{levelCap}}!", + "moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.", + "moveDisabled": "{{moveName}} is disabled!", + "noPokeballForce": "An unseen force\nprevents using Poké Balls.", + "noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!", + "noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!", + "noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!", + "noEscapeForce": "An unseen force\nprevents escape.", + "noEscapeTrainer": "You can't run\nfrom a trainer battle!", + "noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!", + "runAwaySuccess": "You got away safely!", + "runAwayCannotEscape": 'You can\'t escape!', + "escapeVerbSwitch": "switching", + "escapeVerbFlee": "fleeing", + "notDisabled": "{{moveName}} is disabled\nno more!", + "skipItemQuestion": "Are you sure you want to skip taking an item?", + "eggHatching": "Oh?", + "ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?" +} as const; \ No newline at end of file diff --git a/src/locales/it/fight-ui-handler.ts b/src/locales/it/fight-ui-handler.ts new file mode 100644 index 00000000000..1ce9e0317bf --- /dev/null +++ b/src/locales/it/fight-ui-handler.ts @@ -0,0 +1,6 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const fightUiHandler: SimpleTranslationEntries = { + "pp": "PP", + "power": "POWER", +} as const; \ No newline at end of file diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 118c1dccb5f..9812236b7f0 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -1,5 +1,10 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; +/** + * The menu namespace holds most miscellaneous text that isn't directly part of the game's + * contents or directly related to Pokemon data. This includes menu navigation, settings, + * account interactions, descriptive text, etc. + */ export const menu: SimpleTranslationEntries = { "cancel": "Annulla", "continue": "Continua", @@ -7,14 +12,32 @@ export const menu: SimpleTranslationEntries = { "loadGame": "Carica Partita", "dailyRun": "Corsa Giornaliera (Beta)", "selectGameMode": "Seleziona una modalità di gioco.", + "logInOrCreateAccount": "Log in or create an account to start. No email required!", + "username": "Username", + "password": "Password", + "login": "Login", + "register": "Register", + "emptyUsername": "Username must not be empty", + "invalidLoginUsername": "The provided username is invalid", + "invalidRegisterUsername": "Username must only contain letters, numbers, or underscores", + "invalidLoginPassword": "The provided password is invalid", + "invalidRegisterPassword": "Password must be 6 characters or longer", + "usernameAlreadyUsed": "The provided username is already in use", + "accountNonExistent": "The provided user does not exist", + "unmatchingPassword": "The provided password does not match", + "passwordNotMatchingConfirmPassword": "Password must match confirm password", + "confirmPassword": "Confirm Password", + "registrationAgeWarning": "By registering, you confirm you are of 13 years of age or older.", + "backToLogin": "Back to Login", + "failedToLoadSaveData": "Failed to load save data. Please reload the page.\nIf this continues, please contact the administrator.", + "sessionSuccess": "Session loaded successfully.", + "failedToLoadSession": "Your session data could not be loaded.\nIt may be corrupted.", + "boyOrGirl": "Are you a boy or a girl?", + "boy": "Boy", + "girl": "Girl", "dailyRankings": "Daily Rankings", "weeklyRankings": "Weekly Rankings", "noRankings": "No Rankings", "loading": "Loading…", - "playersOnline": "Players Online", - "hitResultCriticalHit": "A critical hit!", - "hitResultSuperEffective": "It's super effective!", - "hitResultNotVeryEffective": "It's not very effective…", - "hitResultNoEffect": "It doesn't affect {{pokemonName}}!", - "hitResultOneHitKO": "It's a one-hit KO!" + "playersOnline": "Players Online" } as const; \ No newline at end of file diff --git a/src/phases.ts b/src/phases.ts index 2e0b8425567..72f0e10cc3e 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -815,14 +815,14 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) - return i18next.t('menu:bossAppeared', {bossName: enemyField[0].name}); + return i18next.t('battle:bossAppeared', {bossName: enemyField[0].name}); if (this.scene.currentBattle.battleType === BattleType.TRAINER) - return i18next.t('menu:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); + return i18next.t('battle:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); return enemyField.length === 1 - ? i18next.t('menu:singleWildAppeared', {pokemonName: enemyField[0].name}) - : i18next.t('menu:multiWildAppeared', {pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name}) + ? i18next.t('battle:singleWildAppeared', {pokemonName: enemyField[0].name}) + : i18next.t('battle:multiWildAppeared', {pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name}) } doEncounterCommon(showEncounterMessage: boolean = true) { @@ -1187,7 +1187,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { } if (this.player) { - this.scene.ui.showText(i18next.t('menu:playerGo', { pokemonName: this.getPokemon().name })); + this.scene.ui.showText(i18next.t('battle:playerGo', { pokemonName: this.getPokemon().name })); if (this.player) this.scene.pbTray.hide(); this.scene.trainer.setTexture(`trainer_${this.scene.gameData.gender === PlayerGender.FEMALE ? 'f' : 'm'}_back_pb`); @@ -1355,8 +1355,8 @@ export class SwitchSummonPhase extends SummonPhase { applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, pokemon); this.scene.ui.showText(this.player ? - i18next.t('menu:playerComeBack', { pokemonName: pokemon.name }) : - i18next.t('menu:trainerComeBack', { + i18next.t('battle:playerComeBack', { pokemonName: pokemon.name }) : + i18next.t('battle:trainerComeBack', { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), pokemonName: pokemon.name }) @@ -1396,8 +1396,8 @@ export class SwitchSummonPhase extends SummonPhase { party[this.fieldIndex] = switchedPokemon; const showTextAndSummon = () => { this.scene.ui.showText(this.player ? - i18next.t('menu:playerGo', { pokemonName: switchedPokemon.name }) : - i18next.t('menu:trainerGo', { + i18next.t('battle:playerGo', { pokemonName: switchedPokemon.name }) : + i18next.t('battle:trainerGo', { trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), pokemonName: this.getPokemon().name }) @@ -1544,7 +1544,7 @@ export class CheckSwitchPhase extends BattlePhase { return; } - this.scene.ui.showText(i18next.t('menu:switchQuestion', { pokemonName: this.useName ? pokemon.name : i18next.t('menu:pokemon') }), null, () => { + this.scene.ui.showText(i18next.t('battle:switchQuestion', { pokemonName: this.useName ? pokemon.name : i18next.t('battle:pokemon') }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); @@ -1564,7 +1564,7 @@ export class SummonMissingPhase extends SummonPhase { } preSummon(): void { - this.scene.ui.showText(i18next.t('menu:sendOutPokemon', { pokemonName: this.getPokemon().name})); + this.scene.ui.showText(i18next.t('battle:sendOutPokemon', { pokemonName: this.getPokemon().name})); this.scene.time.delayedCall(250, () => this.summon()); } } @@ -1579,7 +1579,7 @@ export class LevelCapPhase extends FieldPhase { this.scene.ui.setMode(Mode.MESSAGE).then(() => { this.scene.playSound('level_up_fanfare'); - this.scene.ui.showText(i18next.t('menu:levelCapUp', { levelCap: this.scene.getMaxExpLevel() }), null, () => this.end(), null, true); + this.scene.ui.showText(i18next.t('battle:levelCapUp', { levelCap: this.scene.getMaxExpLevel() }), null, () => this.end(), null, true); this.executeForAll(pokemon => pokemon.updateInfo(true)); }); } @@ -1673,7 +1673,7 @@ export class CommandPhase extends FieldPhase { const move = playerPokemon.getMoveset()[cursor]; if (move.getName().endsWith(' (N)')) { this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:moveNotImplemented', { moveName: move.getName().slice(0, -4) }), null, () => { + this.scene.ui.showText(i18next.t('battle:moveNotImplemented', { moveName: move.getName().slice(0, -4) }), null, () => { this.scene.ui.clearText(); this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); }, null, true); @@ -1692,7 +1692,7 @@ export class CommandPhase extends FieldPhase { const move = playerPokemon.getMoveset()[cursor]; if (playerPokemon.summonData.disabledMove === move.moveId) { this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:moveDisabled', { moveName: move.getName() }), null, () => { + this.scene.ui.showText(i18next.t('battle:moveDisabled', { moveName: move.getName() }), null, () => { this.scene.ui.clearText(); this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); }, null, true); @@ -1703,14 +1703,14 @@ export class CommandPhase extends FieldPhase { if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarters).length - 1))) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballForce'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballForce'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); } else if (this.scene.currentBattle.battleType === BattleType.TRAINER) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballTrainer'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballTrainer'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1719,7 +1719,7 @@ export class CommandPhase extends FieldPhase { if (targets.length > 1) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballMulti'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballMulti'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1728,7 +1728,7 @@ export class CommandPhase extends FieldPhase { if (targetPokemon.isBoss() && targetPokemon.bossSegmentIndex >= 1 && cursor < PokeballType.MASTER_BALL) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noPokeballStrong'), null, () => { + this.scene.ui.showText(i18next.t('battle:noPokeballStrong'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1748,14 +1748,14 @@ export class CommandPhase extends FieldPhase { if (!isSwitch && this.scene.arena.biomeType === Biome.END) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noEscapeForce'), null, () => { + this.scene.ui.showText(i18next.t('battle:noEscapeForce'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); } else if (!isSwitch && this.scene.currentBattle.battleType === BattleType.TRAINER) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t('menu:noEscapeTrainer'), null, () => { + this.scene.ui.showText(i18next.t('battle:noEscapeTrainer'), null, () => { this.scene.ui.showText(null, 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); @@ -1778,10 +1778,10 @@ export class CommandPhase extends FieldPhase { this.scene.ui.setMode(Mode.MESSAGE); } this.scene.ui.showText( - i18next.t('menu:noEscapePokemon', { + i18next.t('battle:noEscapePokemon', { pokemonName: this.scene.getPokemonById(trapTag.sourceId).name, moveName: trapTag.getMoveName(), - escapeVerb: isSwitch ? i18next.t('menu:escapeVerbSwitch') : i18next.t('menu:escapeVerbFlee') + escapeVerb: isSwitch ? i18next.t('battle:escapeVerbSwitch') : i18next.t('battle:escapeVerbFlee') }), null, () => { @@ -2031,7 +2031,7 @@ export class TurnEndPhase extends FieldPhase { pokemon.lapseTags(BattlerTagLapseType.TURN_END); if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) { - this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('menu:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name }))); + this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('battle:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name }))); pokemon.summonData.disabledMove = Moves.NONE; } @@ -2339,7 +2339,7 @@ export class MovePhase extends BattlePhase { } showFailedText(failedText: string = null): void { - this.scene.queueMessage(failedText || i18next.t('menu:attackFailed')); + this.scene.queueMessage(failedText || i18next.t('battle:attackFailed')); } end() { @@ -2402,7 +2402,7 @@ export class MoveEffectPhase extends PokemonPhase { moveHistoryEntry.result = MoveResult.MISS; applyMoveAttrs(MissEffectAttr, user, null, this.move.getMove()); } else { - this.scene.queueMessage(i18next.t('menu:attackFailed')); + this.scene.queueMessage(i18next.t('battle:attackFailed')); moveHistoryEntry.result = MoveResult.FAIL; } return this.end(); @@ -2486,7 +2486,7 @@ export class MoveEffectPhase extends PokemonPhase { else { const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0); if (hitsTotal > 1) - this.scene.queueMessage(i18next.t('menu:attackHitsCount', { count: hitsTotal })); + this.scene.queueMessage(i18next.t('battle:attackHitsCount', { count: hitsTotal })); this.scene.applyModifiers(HitHealModifier, this.player, user); } } @@ -3342,7 +3342,7 @@ export class TrainerVictoryPhase extends BattlePhase { this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); } - this.scene.ui.showText(i18next.t('menu:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { + this.scene.ui.showText(i18next.t('battle:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { const victoryMessages = this.scene.currentBattle.trainer.getVictoryMessages(); const showMessage = () => { let message: string; @@ -3609,7 +3609,7 @@ export class ExpPhase extends PlayerPartyMemberPokemonPhase { let exp = new Utils.NumberHolder(this.expValue); this.scene.applyModifiers(ExpBoosterModifier, true, exp); exp.value = Math.floor(exp.value); - this.scene.ui.showText(i18next.t('menu:expGain', { pokemonName: pokemon.name, exp: exp.value }), null, () => { + this.scene.ui.showText(i18next.t('battle:expGain', { pokemonName: pokemon.name, exp: exp.value }), null, () => { const lastLevel = pokemon.level; let newLevel: integer; pokemon.addExp(exp.value); @@ -3697,7 +3697,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { pokemon.calculateStats(); pokemon.updateInfo(); this.scene.playSound('level_up_fanfare'); - this.scene.ui.showText(i18next.t('menu:levelUp', { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); + this.scene.ui.showText(i18next.t('battle:levelUp', { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); if (this.level <= 100) { const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1); for (let lm of levelMoves) @@ -3746,7 +3746,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { .then(() => { this.scene.ui.setMode(messageMode).then(() => { this.scene.playSound('level_up_fanfare'); - this.scene.ui.showText(i18next.t('menu:learnMove', { pokemonName: pokemon.name, moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMove', { pokemonName: pokemon.name, moveName: move.name }), null, () => { this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true); this.end(); }, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true); @@ -3755,15 +3755,15 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { }); } else { this.scene.ui.setMode(messageMode).then(() => { - this.scene.ui.showText(i18next.t('menu:learnMovePrompt', { pokemonName: pokemon.name, moveName: move.name }), null, () => { - this.scene.ui.showText(i18next.t('menu:learnMoveLimitReached', { pokemonName: pokemon.name }), null, () => { - this.scene.ui.showText(i18next.t('menu:learnMoveReplaceQuestion', { moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMovePrompt', { pokemonName: pokemon.name, moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveLimitReached', { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveReplaceQuestion', { moveName: move.name }), null, () => { const noHandler = () => { this.scene.ui.setMode(messageMode).then(() => { - this.scene.ui.showText(i18next.t('menu:learnMoveStopTeaching', { moveName: move.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveStopTeaching', { moveName: move.name }), null, () => { this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setMode(messageMode); - this.scene.ui.showText(i18next.t('menu:learnMoveNotLearned', { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true); + this.scene.ui.showText(i18next.t('battle:learnMoveNotLearned', { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true); }, () => { this.scene.ui.setMode(messageMode); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -3774,7 +3774,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { }; this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setMode(messageMode); - this.scene.ui.showText(i18next.t('menu:learnMoveForgetQuestion'), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveForgetQuestion'), null, () => { this.scene.ui.setModeWithoutClear(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => { if (moveIndex === 4) { noHandler(); @@ -3782,7 +3782,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { } this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.showText('@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Poof!', null, () => { - this.scene.ui.showText(i18next.t('menu:learnMoveForgetSuccess', { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => { + this.scene.ui.showText(i18next.t('battle:learnMoveForgetSuccess', { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => { this.scene.ui.showText('And…', null, () => { pokemon.setMove(moveIndex, Moves.NONE); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); @@ -4097,7 +4097,7 @@ export class AttemptCapturePhase extends PokemonPhase { this.scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); - this.scene.ui.showText(i18next.t('menu:pokemonCaught', { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:pokemonCaught', { pokemonName: pokemon.name }), null, () => { const end = () => { this.scene.pokemonInfoContainer.hide(); this.removePb(); @@ -4183,7 +4183,7 @@ export class AttemptRunPhase extends PokemonPhase { if (playerPokemon.randSeedInt(256) < escapeChance.value) { this.scene.playSound('flee'); - this.scene.queueMessage(i18next.t('menu:runAwaySuccess'), null, true, 500); + this.scene.queueMessage(i18next.t('battle:runAwaySuccess'), null, true, 500); this.scene.tweens.add({ targets: [ this.scene.arenaEnemy, enemyField ].flat(), @@ -4204,7 +4204,7 @@ export class AttemptRunPhase extends PokemonPhase { this.scene.pushPhase(new BattleEndPhase(this.scene)); this.scene.pushPhase(new NewBattlePhase(this.scene)); } else - this.scene.queueMessage(i18next.t('menu:runAwayCannotEscape'), null, true, 500); + this.scene.queueMessage(i18next.t('battle:runAwayCannotEscape'), null, true, 500); this.end(); } @@ -4236,7 +4236,7 @@ export class SelectModifierPhase extends BattlePhase { const modifierSelectCallback = (rowCursor: integer, cursor: integer) => { if (rowCursor < 0 || cursor < 0) { - this.scene.ui.showText(i18next.t('menu:skipItemQuestion'), null, () => { + this.scene.ui.showText(i18next.t('battle:skipItemQuestion'), null, () => { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { this.scene.ui.revertMode(); this.scene.ui.setMode(Mode.MESSAGE); @@ -4415,7 +4415,7 @@ export class EggLapsePhase extends Phase { }); if (eggsToHatch.length) { - this.scene.queueMessage(i18next.t('menu:eggHatching')); + this.scene.queueMessage(i18next.t('battle:eggHatching')); for (let egg of eggsToHatch) this.scene.unshiftPhase(new EggHatchPhase(this.scene, egg)); @@ -4509,7 +4509,7 @@ export class ScanIvsPhase extends PokemonPhase { const pokemon = this.getPokemon(); - this.scene.ui.showText(i18next.t('menu:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => { + this.scene.ui.showText(i18next.t('battle:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.clearText(); diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 22a407c3b42..4d770ae0a12 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -13,6 +13,12 @@ import { menuUiHandler as frMenuUiHandler } from '../locales/fr/menu-ui-handler. import { menuUiHandler as itMenuUiHandler } from '../locales/it/menu-ui-handler.js'; import { menuUiHandler as deMenuUiHandler } from '../locales/de/menu-ui-handler.js'; +import { battle as enBattle } from '../locales/en/battle'; +import { battle as esBattle } from '../locales/es/battle'; +import { battle as itBattle } from '../locales/it/battle'; +import { battle as frBattle } from '../locales/fr/battle'; +import { battle as deBattle } from '../locales/de/battle'; + import { move as enMove } from '../locales/en/move'; import { move as esMove } from '../locales/es/move'; import { move as frMove } from '../locales/fr/move'; @@ -45,7 +51,10 @@ import { commandUiHandler as frCommandUiHandler } from '../locales/fr/command-ui import { commandUiHandler as deCommandUiHandler } from '../locales/de/command-ui-handler'; import { fightUiHandler as enFightUiHandler } from '../locales/en/fight-ui-handler'; +import { fightUiHandler as esFightUiHandler } from '../locales/es/fight-ui-handler'; import { fightUiHandler as frFightUiHandler } from '../locales/fr/fight-ui-handler'; +import { fightUiHandler as itFightUiHandler } from '../locales/it/fight-ui-handler'; +import { fightUiHandler as deFightUiHandler } from '../locales/de/fight-ui-handler'; import { tutorial as enTutorial } from '../locales/en/tutorial'; import { tutorial as esTutorial } from '../locales/es/tutorial'; @@ -113,6 +122,7 @@ export function initI18n(): void { en: { menu: enMenu, menuUiHandler: enMenuUiHandler, + battle: enBattle, move: enMove, ability: enAbility, pokeball: enPokeball, @@ -125,17 +135,20 @@ export function initI18n(): void { es: { menu: esMenu, menuUiHandler: esMenuUiHandler, + battle: esBattle, move: esMove, ability: esAbility, pokeball: esPokeball, pokemon: esPokemon, pokemonStat: esPokemonStat, commandUiHandler: esCommandUiHandler, + fightUiHandler: esFightUiHandler, tutorial: esTutorial, }, fr: { menu: frMenu, menuUiHandler: frMenuUiHandler, + battle: frBattle, move: frMove, ability: frAbility, pokeball: frPokeball, @@ -148,18 +161,22 @@ export function initI18n(): void { it: { menu: itMenu, menuUiHandler: itMenuUiHandler, + battle: itBattle, pokemonStat: itPokemonStat, + fightUiHandler: itFightUiHandler, tutorial: itTutorial, }, de: { menu: deMenu, menuUiHandler: deMenuUiHandler, + battle: deBattle, move: deMove, ability: deAbility, pokeball: dePokeball, pokemon: dePokemon, pokemonStat: dePokemonStat, commandUiHandler: deCommandUiHandler, + fightUiHandler: deFightUiHandler, tutorial: deTutorial, } }, @@ -173,6 +190,7 @@ declare module 'i18next' { menu: typeof enMenu; menuUiHandler: typeof enMenuUiHandler; move: typeof enMove; + battle: typeof enBattle, ability: typeof enAbility; pokeball: typeof enPokeball; pokemon: typeof enPokemon; From ad59c0a7c4ae8543aba02e9ed39052545207ceac Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Wed, 1 May 2024 18:05:34 -0500 Subject: [PATCH 05/28] Fixed Rounding Error For TargetHalfHpDamageAttr Moves that deal half of a target's HP were not able to deal damage if the target had 1 HP. Used Math.max to ensure 1 is the lowest this value ever evaluates to. --- src/data/move.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index d6367794a35..ad1ae31c06f 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -557,7 +557,7 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr { } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - (args[0] as Utils.IntegerHolder).value = Math.floor(target.hp / 2); + (args[0] as Utils.IntegerHolder).value = Math.max(Math.floor(target.hp / 2), 1); return true; } From 86b0596a60d831eadc78de3ae57b202ab780d14c Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 19:28:07 -0400 Subject: [PATCH 06/28] Add rogue achievement and voucher tier --- public/images/ui/achv_bar_4.png | Bin 458 -> 418 bytes public/images/ui/achv_bar_5.png | Bin 0 -> 458 bytes public/images/ui/legacy/achv_bar_4.png | Bin 433 -> 344 bytes public/images/ui/legacy/achv_bar_5.png | Bin 0 -> 433 bytes src/system/achv.ts | 5 ++++- src/system/voucher.ts | 2 +- 6 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 public/images/ui/achv_bar_5.png create mode 100644 public/images/ui/legacy/achv_bar_5.png diff --git a/public/images/ui/achv_bar_4.png b/public/images/ui/achv_bar_4.png index cc06af91620256e98ab26c762a49fe432cf584ce..debf8bfe2114a634e6f39e696088cca466d3a8d6 100644 GIT binary patch delta 394 zcmV;50d@Y$1EK?v7k?%Q0ssI2#x!fF00001b5ch_0Itp)=>Px$LPe5nZXH! zFc3wpBK4#ItH>!mqy-DuyQkdKgXJs;o?T>M+#TW)c4Hjj!yw5ej4ywZ@7OtG5Q0D_ z=9oHT03}l>fKmn}d0##5Rh3dHjAMy$o##JeiIEq)5tlraDt|->D02anU1ET;v*5Y| z6hJ9EhM^QFK*77B-cF_7tPTmjJD!-mLD1)_}DDB>PJ|%hYjCu6^6oT5=pb!Y! zy*5zP;-JJXgYq0l_A=TA*Fe!sWS!@0plFkZ$Olj|-U?6vrOa?bDF;evZ{Ebgrfs?@ z+(6HB&)Ca o0#&KYjDGtnRR9104rN$LW=%~1DgXcg2mk;800000(v!Ra4yk6PRR910 delta 411 zcmV;M0c8H71Ih!C7k?-S1^@s6b6lN|00001b5ch_0Itp)=>Px$YDq*vRA_DP__;of?62bTd;NQQCQhHNFtOB4BZe*7Di40I}8YfDoB_3*|Oia zMUmn^pOP0RegQ?4r?39U(RGNJ=(r9L8!B8F6)uc;y_*&*X^7a3YUo7pI@nQ#`fV5VOgs5Im<(9|lzo(r!xMo&& z-}A2B{AZ(YPQEzf@0RS;5BDB9#ED&hE3w3Un#k-;jNdNnO}=>J*2h|x>>UOW&0OMc zt=yjrT8X)$q#B=8ROsDu0jaQ>BteDVa??MX7Vv(E4&|GC<6uLL{*U??yJc5Pd0V!AT5KPxnOMwJ q?cnataG_EN7zKQ(5uRzjz6@GGHU|)cz@^~HAj;F#&t;ucLK6T2Ilt8a literal 0 HcmV?d00001 diff --git a/public/images/ui/legacy/achv_bar_4.png b/public/images/ui/legacy/achv_bar_4.png index dae7a30dec065d67334e6c7cbac6c05716d38fef..d52fbfd055e8a4839ab16a495f9dcccbcbdd71a5 100644 GIT binary patch delta 329 zcmdnUe1mC%L_G^L0|P^2QNtb}#aJBV?!<0h-v4*igLY0h6zQhc&hD}*Eg|98VGW)C zo{X+< zFWp}Gqp9Qyz2uY-l{Gwk_ZS)E-p|raFcyCUbTnUTglC$sFM}44%>l$9a4C2)i1Kvx Kb6Mw<&;$VCBZQ*> delta 419 zcmV;U0bKsr0n6zU{cp-{T%Si1Th`~q2ngF_cV1fg~gbjao)E?p$akUdLgUA%IME?RSG;`1Nd zlw5y3(n9lUD0P2!^ZxSo3buWR`v;gTr<(kjR)&tU1aY2H>wgb&3=6Jl7vMF4{rLQZ zI8O@)vEL_eUdOO7>J2ejPBmRT8RsbmR=@B9wq34i!!>OLX}Iy!#O@Xc06>t2wJcEn zz}r-mB>;d?ZwS4-yMr{u)$t7H50^?8wHVLgt^8J^%e%ZIf1`?2W7l;~mA_U*9bReG zMsR`?oDrPhjDO&}nclSDu>`NUi@TF{NFOx-Tbo@x`5Y#$z$gH&I9Hu3-f N002ovPDHLkV1jh6!Y}{; diff --git a/public/images/ui/legacy/achv_bar_5.png b/public/images/ui/legacy/achv_bar_5.png new file mode 100644 index 0000000000000000000000000000000000000000..dae7a30dec065d67334e6c7cbac6c05716d38fef GIT binary patch literal 433 zcmV;i0Z#sjP)7@C0mv(P8pKm(nTD)6%^_uSfNn5=~%k@9sB}WgM&jCK?I?84s^)oATC`b z$&fuuW?j5;i7r}mY2x!A+mu{?J<>w+YAAJocJu!7_6oLrhx-SZET@|Mm{x|4vIKFS zQtJJ2ejPBmRT8RsbmR=@B9wq34i!!>OL zX}Iy!#O@Xc06>t2wJcEnz}r-mB>;d?ZwS4-yMr{u)$t7H50^?8wHVLgt^8J^%e%ZI zf1`?2W7l;~mA_U*9bReGMsR`?oDrPhjNrSO-n8Gb1h2S@yOVZEA2k46>};po}6Pyv8;Os}>i}76fLh3kY9ew$WZD94`t$cWUzVgMi z^>*cN!Q~t9|HB(sS-f5s!5zawlqEYmY9cSViCv%G!Z9oWpA!%qrm8l1ZfY}B#hIRJ b6O(Ko9+rbtUwk(500000NkvXXu0mjfWv;=( literal 0 HcmV?d00001 diff --git a/src/system/achv.ts b/src/system/achv.ts index 2307347db3a..f63dd5b2810 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -7,6 +7,7 @@ export enum AchvTier { COMMON, GREAT, ULTRA, + ROGUE, MASTER } @@ -50,8 +51,10 @@ export class Achv { } getTier(): AchvTier { - if (this.score >= 100) + if (this.score >= 150) return AchvTier.MASTER; + if (this.score >= 100) + return AchvTier.ROGUE; if (this.score >= 50) return AchvTier.ULTRA; if (this.score >= 25) diff --git a/src/system/voucher.ts b/src/system/voucher.ts index c3bae6f0878..276e74eeb0d 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -44,7 +44,7 @@ export class Voucher { case VoucherType.PREMIUM: return AchvTier.ULTRA; case VoucherType.GOLDEN: - return AchvTier.MASTER; + return AchvTier.ROGUE; } } } From 2f8000885e2db76b607fdff06c26b7696284d491 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 19:29:04 -0400 Subject: [PATCH 07/28] Fix coloring error in rogue achievement bar --- public/images/ui/achv_bar_4.png | Bin 418 -> 318 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/ui/achv_bar_4.png b/public/images/ui/achv_bar_4.png index debf8bfe2114a634e6f39e696088cca466d3a8d6..f14026c7a34c13829053ffaa2291bda986ab9a3c 100644 GIT binary patch delta 270 zcmZ3)ypL&uc)bP-GXn!dV^PB%AjMc5hfTEf3IKb_|iYz z`ktrkcX2!j)5|Irh^<_ql=sx>kNm}{?V1yo#iTQ9o;sXAImK%7!4DyQs>T&o#ClL1!5l5_R&8W;0LU KRzA6gQ4IjBLuz*b delta 394 zcmV;50d@Yq0-^(u7k?%Q0ssI2#x!fF00001b5ch_0Itp)=>Px$LPe5nZXH! zFc3wpBK4#ItH>!mqy-DuyQkdKgXJs;o?T>M+#TW)c4Hjj!yw5ej4ywZ@7OtG5Q0D_ z=9oHT03}l>fKmn}d0##5Rh3dHjAMy$o##JeiIEq)5tlraDt|->D02anU1ET;v*5Y| z6hJ9EhM^QFK*77B-cF_7tPTmjJD!-mLD1)_}DDB>PJ|%hYjCu6^6oT5=pb!Y! zy*5zP;-JJXgYq0l_A=TA*Fe!sWS!@0plFkZ$Olj|-U?6vrOa?bDF;evZ{Ebgrfs?@ z+(6HB&)Ca o0#&KYjDGtnRR9104rN$LW=%~1DgXcg2mk;800000(vvU&4wJ#8yZ`_I From ba5bef123cffbadffd120f90960f94ea99f6efea Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 1 May 2024 19:42:06 -0400 Subject: [PATCH 08/28] Load missed master achievement bar --- src/loading-scene.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 875d618ec0f..d0751e9a2da 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -67,6 +67,7 @@ export class LoadingScene extends SceneBase { this.loadImage('achv_bar_2', 'ui'); this.loadImage('achv_bar_3', 'ui'); this.loadImage('achv_bar_4', 'ui'); + this.loadImage('achv_bar_5', 'ui'); this.loadImage('shiny_star', 'ui', 'shiny.png'); this.loadImage('shiny_star_1', 'ui', 'shiny_1.png'); this.loadImage('shiny_star_2', 'ui', 'shiny_2.png'); From 6d9424e43158123f9bceff53f5499f53f59ea694 Mon Sep 17 00:00:00 2001 From: Xavion3 Date: Thu, 2 May 2024 14:22:30 +1000 Subject: [PATCH 09/28] Implement Gastro Acid (#393) --- src/data/move.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index ad1ae31c06f..e1694ede8a3 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3594,6 +3594,25 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr { } } +export class SuppressAbilitiesAttr extends MoveEffectAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if (!super.apply(user, target, move, args)) + return false; + + target.summonData.abilitySuppressed = true; + + target.scene.queueMessage(getPokemonMessage(target, ` ability\nwas suppressed!`)); + + return true; + } + + getCondition(): MoveConditionFunc { + return (user, target, move) => !target.getAbility().hasAttr(UnsuppressableAbilityAbAttr); + } +} + + + export class TransformAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { return new Promise(resolve => { @@ -4831,7 +4850,7 @@ export function initMoves() { new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4) .unimplemented(), new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4) - .unimplemented(), + .attr(SuppressAbilitiesAttr), new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4) .attr(AddBattlerTagAttr, BattlerTagType.NO_CRIT, false, false, 5) .target(MoveTarget.USER_SIDE) From a1bb0e7baf00d4f11929e360652537a2dc7dfc8a Mon Sep 17 00:00:00 2001 From: Lugiad Date: Thu, 2 May 2024 06:26:24 +0200 Subject: [PATCH 10/28] Updated French transaltion for tutorial.ts (#375) Translation of "statChange" + some remaning typos --- src/locales/fr/tutorial.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/locales/fr/tutorial.ts b/src/locales/fr/tutorial.ts index b60ccc03b5d..1502b285356 100644 --- a/src/locales/fr/tutorial.ts +++ b/src/locales/fr/tutorial.ts @@ -8,7 +8,7 @@ export const tutorial: SimpleTranslationEntries = { $Tout signalement de bugs passe par le serveur Discord. $Si le jeu est lent, vérifiez que l’Accélération Matérielle est activée dans les paramètres du navigateur.`, - "accessMenu": `Accédez au menu avec M ou Échap lors de l'attente d’une\naction. + "accessMenu": `Accédez au menu avec M ou Échap lors de l’attente d’une\naction. $Il contient les paramètres et diverses fonctionnalités`, "menu": `Vous pouvez accéder aux paramètres depuis ce menu. @@ -17,17 +17,20 @@ export const tutorial: SimpleTranslationEntries = { $jetez-y un œil !`, "starterSelect": `Choisissez vos starters depuis cet écran.\nIls formeront votre équipe de départ. - $Chacun possède une valeur. Votre équipe peut avoir jusqu’à\n6 membres, tant que vous ne dépassez pas un coût de 10. + $Chacun possède une valeur. Votre équipe peut avoir jusqu’à\n6 membres, tant que vous ne dépassez pas un cout de 10. $Vous pouvez aussi choisir le sexe, le talent et la forme en\nfonction des variants déjà capturés ou éclos. $Les IVs d’un starter sont les meilleurs de tous ceux de son\nespèce déjà obtenus. Essayez donc d’en obtenir plusieurs !`, "pokerus": `Chaque jour, 3 starters tirés aléatoirement ont un contour $violet. Si un starter que vous possédez l’a, essayez de - $ l’ajouter à votre équipe. Vérifiez bien son résumé !`, + $l’ajouter à votre équipe. Vérifiez bien son résumé !`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, + "statChange": `Les changements de stats restent à travers les combats tant que le Pokémon + $n’est pas rappelé. + $Vos Pokémon sont rappelés avant un combat de Dresseur et avant d’entrer + $dans un nouveau biome. + $Vous pouvez également voir en combat les changements de stats d’un Pokémon + $en maintenant C ou Maj.`, "selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre qu’un. $Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents. @@ -44,4 +47,4 @@ export const tutorial: SimpleTranslationEntries = { $Les Pokémon issus d’Œufs ont généralement de\nmeilleurs IVs que les Pokémon sauvages. $Certains Pokémon ne peuvent être obtenus\nque dans des Œufs. $Il y a 3 différentes machines à actionner avec différents\nbonus, prenez celle qui vous convient le mieux !`, -} as const; \ No newline at end of file +} as const; From c9152cda3f27c0277cedc7782cad00a39428163f Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Thu, 2 May 2024 00:17:32 -0500 Subject: [PATCH 11/28] Fix Mobile PWA not showing in true Fullscreen (#394) * Fixed Rounding Error For TargetHalfHpDamageAttr Moves that deal half of a target's HP were not able to deal damage if the target had 1 HP. Used Math.max to ensure 1 is the lowest this value ever evaluates to. * Fix Mobile PWA not showing in true Fullscreen adding "fullscreen" to the display attribute wasn't enough, but adding it to the start_url attribute was. This does not appear to affect PC (which is good since it shouldn't). * Allow any orientation for mobile PWA remove the orientation restriction since it doesn't prevent fullscreen PWA from displaying properly. --- public/manifest.webmanifest | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest index c75c70a8d45..4b5f2dbadd1 100644 --- a/public/manifest.webmanifest +++ b/public/manifest.webmanifest @@ -3,9 +3,8 @@ "short_name": "PokéRogue", "description": "A Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, and reaching Pokémon stats you never thought possible.", "scope": "/", - "start_url": "/", + "start_url": "https://pokerogue.net", "display": "fullscreen", - "orientation": "landscape", "background_color": "#8c8c8c", "theme_color": "#8c8c8c", "icons": [ From 71893e8428f410c8d22ee31abb87223ba0336977 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Thu, 2 May 2024 14:34:59 +0200 Subject: [PATCH 12/28] Update Spanish fight-ui-handler.ts --- src/locales/es/fight-ui-handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts index 1ce9e0317bf..b431e3b7065 100644 --- a/src/locales/es/fight-ui-handler.ts +++ b/src/locales/es/fight-ui-handler.ts @@ -2,5 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "POWER", -} as const; \ No newline at end of file + "power": "POTENCIA", +} as const; From 10506f9cf58975088836db96aad2fca691ab7889 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Thu, 2 May 2024 14:37:05 +0200 Subject: [PATCH 13/28] Update italian pokemon-stat.ts (#389) * Update italian pokemon-stat.ts * Update italian pokemon-stat.ts --- src/locales/it/pokemon-stat.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/locales/it/pokemon-stat.ts b/src/locales/it/pokemon-stat.ts index 7a209461b11..a3a62edebe2 100644 --- a/src/locales/it/pokemon-stat.ts +++ b/src/locales/it/pokemon-stat.ts @@ -1,16 +1,16 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const pokemonStat: SimpleTranslationEntries = { - "HP": "Max. HP", - "HPshortened": "MaxHP", - "ATK": "Attack", - "ATKshortened": "Atk", - "DEF": "Defense", - "DEFshortened": "Def", - "SPATK": "Sp. Atk", - "SPATKshortened": "SpAtk", - "SPDEF": "Sp. Def", - "SPDEFshortened": "SpDef", - "SPD": "Speed", - "SPDshortened": "Spd" -} as const; \ No newline at end of file + "HP": "PS Max", + "HPshortened": "PS", + "ATK": "Attacco", + "ATKshortened": "Att", + "DEF": "Difensa", + "DEFshortened": "Dif", + "SPATK": "Att. Sp.", + "SPATKshortened": "AttSp", + "SPDEF": "Dif. Sp.", + "SPDEFshortened": "DifSp", + "SPD": "Velocità", + "SPDshortened": "Vel" +} as const; From 0185dd639e0238b60a248d4f0f51dc89c245bebe Mon Sep 17 00:00:00 2001 From: James Lin Date: Thu, 2 May 2024 05:44:10 -0700 Subject: [PATCH 14/28] Catch global errors and rejected promises and display them in an alert box. (#351) * Catch errors and rejected promises. * Clean up --- src/main.ts | 16 ++++++++++++++++ src/phases.ts | 2 ++ src/ui/daily-run-scoreboard.ts | 2 +- src/ui/title-ui-handler.ts | 3 +++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 6a00693fc71..4b181f58174 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,22 @@ import BBCodeText from 'phaser3-rex-plugins/plugins/bbcodetext'; import TransitionImagePackPlugin from 'phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin.js'; import { LoadingScene } from './loading-scene'; + +// Catch global errors and display them in an alert so users can report the issue. +window.onerror = function (message, source, lineno, colno, error) { + console.error(error); + let errorString = `Received unhandled error. Open browser console and click OK to see details.\nError: ${message}\nSource: ${source}\nLine: ${lineno}\nColumn: ${colno}\nStack: ${error.stack}`; + alert(errorString); + // Avoids logging the error a second time. + return true; +}; + +// Catch global promise rejections and display them in an alert so users can report the issue. +window.addEventListener('unhandledrejection', (event) => { + let errorString = `Received unhandled promise rejection. Open browser console and click OK to see details.\nReason: ${event.reason}`; + alert(errorString); + }); + const config: Phaser.Types.Core.GameConfig = { type: Phaser.WEBGL, parent: 'app', diff --git a/src/phases.ts b/src/phases.ts index 72f0e10cc3e..2ffa25aef0f 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -331,6 +331,8 @@ export class TitlePhase extends Phase { this.scene.sessionPlayTime = 0; this.end(); }); + }).catch(err => { + console.error("Failed to load daily run:\n", err); }); }); } diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index 8f7ca0bf110..8b258b3a702 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -167,7 +167,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { } else this.loadingLabel.setText(i18next.t('menu:noRankings')); }); - }); + }).catch(err => { console.error("Failed to load daily rankings:\n", err) }); } } diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index c430764e4da..6f873c6b0a1 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -65,6 +65,9 @@ export default class TitleUiHandler extends OptionSelectUiHandler { this.playerCountLabel.setText(`${stats.playerCount} ${i18next.t("menu:playersOnline")}`); if (this.splashMessage === battleCountSplashMessage) this.splashMessageText.setText(battleCountSplashMessage.replace('{COUNT}', stats.battleCount.toLocaleString('en-US'))); + }) + .catch(err => { + console.error("Failed to fetch title stats:\n", err); }); } From 3a7a48fe833f9ab1a10339f3fdd4b10b190cdae3 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 09:00:36 -0400 Subject: [PATCH 15/28] Temporarily disable error handling --- src/main.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.ts b/src/main.ts index 4b181f58174..b3b4d5f3cc6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,7 +14,7 @@ import { LoadingScene } from './loading-scene'; window.onerror = function (message, source, lineno, colno, error) { console.error(error); let errorString = `Received unhandled error. Open browser console and click OK to see details.\nError: ${message}\nSource: ${source}\nLine: ${lineno}\nColumn: ${colno}\nStack: ${error.stack}`; - alert(errorString); + //alert(errorString); // Avoids logging the error a second time. return true; }; @@ -22,8 +22,9 @@ window.onerror = function (message, source, lineno, colno, error) { // Catch global promise rejections and display them in an alert so users can report the issue. window.addEventListener('unhandledrejection', (event) => { let errorString = `Received unhandled promise rejection. Open browser console and click OK to see details.\nReason: ${event.reason}`; - alert(errorString); - }); + console.error(event.reason); + //alert(errorString); +}); const config: Phaser.Types.Core.GameConfig = { type: Phaser.WEBGL, From 322838cfb5a9d486e0f46e60c85efbeb7f1b564b Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 11:37:06 -0400 Subject: [PATCH 16/28] Move service-worker to public folder --- service-worker.js => public/service-worker.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename service-worker.js => public/service-worker.js (100%) diff --git a/service-worker.js b/public/service-worker.js similarity index 100% rename from service-worker.js rename to public/service-worker.js From ddb4383b1f9620fbc5040189076eba57668e3985 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Thu, 2 May 2024 14:01:57 -0500 Subject: [PATCH 17/28] Move Porygon line down to Rare in Factory biome This makes the Porygon line more common than before. --- src/data/biomes.ts | 12 ++++++------ src/data/move.ts | 5 +---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/data/biomes.ts b/src/data/biomes.ts index d6e84bcbc7c..c6a3c95b631 100644 --- a/src/data/biomes.ts +++ b/src/data/biomes.ts @@ -615,7 +615,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 20: [ Species.MANTINE ] }, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ] }, Species.DHELMISE ] + [TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 52: [ Species.MANTINE ] }, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ] }, Species.DHELMISE ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], @@ -1128,8 +1128,8 @@ export const biomePokemonPools: BiomePokemonPools = { ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ] }, Species.KLEFKI ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] }, { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] } ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] } ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] } ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLINKLANG, Species.KLEFKI ] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, @@ -1319,7 +1319,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] }, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ], [TimeOfDay.DUSK]: [ Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], [TimeOfDay.NIGHT]: [ { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], - [TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 36: [ Species.TOUCANNON ] } ] + [TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 28: [ Species.TOUCANNON ] } ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ Species.EXEGGCUTE, Species.TROPIUS, Species.COMBEE, Species.KOMALA ], @@ -2708,7 +2708,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { ] ], [ Species.PORYGON, Type.NORMAL, -1, [ - [ Biome.FACTORY, BiomePoolTier.SUPER_RARE ], + [ Biome.FACTORY, BiomePoolTier.RARE ], [ Biome.SPACE, BiomePoolTier.SUPER_RARE ], [ Biome.LABORATORY, BiomePoolTier.RARE ] ] @@ -3165,7 +3165,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { ] ], [ Species.PORYGON2, Type.NORMAL, -1, [ - [ Biome.FACTORY, BiomePoolTier.SUPER_RARE ], + [ Biome.FACTORY, BiomePoolTier.RARE ], [ Biome.SPACE, BiomePoolTier.SUPER_RARE ], [ Biome.LABORATORY, BiomePoolTier.RARE ] ] diff --git a/src/data/move.ts b/src/data/move.ts index e1694ede8a3..e300b3ae20d 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3611,8 +3611,6 @@ export class SuppressAbilitiesAttr extends MoveEffectAttr { } } - - export class TransformAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { return new Promise(resolve => { @@ -6357,8 +6355,7 @@ export function initMoves() { }), // TODO Add Instruct/Encore interaction new AttackMove(Moves.COMEUPPANCE, Type.DARK, MoveCategory.PHYSICAL, 1, 100, 10, -1, 0, 9) .attr(CounterDamageAttr, (move: Move) => (move.category === MoveCategory.PHYSICAL || move.category === MoveCategory.SPECIAL), 1.5) - .target(MoveTarget.ATTACKER) - .partial(), + .target(MoveTarget.ATTACKER), new AttackMove(Moves.AQUA_CUTTER, Type.WATER, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 9) .attr(HighCritAttr) .slicingMove() From 9d8f7ddcf0b8afb07df95a10ec7839b8f83b1594 Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Thu, 2 May 2024 14:10:21 -0500 Subject: [PATCH 18/28] Implement Tailwind (#398) Added a new ArenaTagType for Tailwind. Lasts 4 turns including the turn used. --- src/data/arena-tag.ts | 16 ++++++++++++++++ src/data/enums/arena-tag-type.ts | 3 ++- src/data/move.ts | 4 ++-- src/field/pokemon.ts | 5 +++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index a879c68d4ce..8942cfe4b3e 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -482,6 +482,20 @@ export class GravityTag extends ArenaTag { } } +class TailwindTag extends ArenaTag { + constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { + super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side); + } + + onAdd(arena: Arena): void { + arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? '\nyour' : this.side === ArenaTagSide.ENEMY ? '\nthe opposing' : ''} team!`); + } + + onRemove(arena: Arena): void { + arena.scene.queueMessage(`${this.side === ArenaTagSide.PLAYER ? 'Your' : this.side === ArenaTagSide.ENEMY ? 'The opposing' : ''} team's Tailwind petered out!`); + } +} + export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag { switch (tagType) { case ArenaTagType.MIST: @@ -513,5 +527,7 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov return new LightScreenTag(turnCount, sourceId, side); case ArenaTagType.AURORA_VEIL: return new AuroraVeilTag(turnCount, sourceId, side); + case ArenaTagType.TAILWIND: + return new TailwindTag(turnCount, sourceId, side); } } diff --git a/src/data/enums/arena-tag-type.ts b/src/data/enums/arena-tag-type.ts index 8478b6f3f57..2ecac8b5677 100644 --- a/src/data/enums/arena-tag-type.ts +++ b/src/data/enums/arena-tag-type.ts @@ -15,5 +15,6 @@ export enum ArenaTagType { GRAVITY = "GRAVITY", REFLECT = "REFLECT", LIGHT_SCREEN = "LIGHT_SCREEN", - AURORA_VEIL = "AURORA_VEIL" + AURORA_VEIL = "AURORA_VEIL", + TAILWIND = "TAILWIND" } diff --git a/src/data/move.ts b/src/data/move.ts index e300b3ae20d..b26af03fc5e 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4805,8 +4805,8 @@ export function initMoves() { .partial(), new StatusMove(Moves.TAILWIND, Type.FLYING, -1, 15, -1, 0, 4) .windMove() - .target(MoveTarget.USER_SIDE) - .unimplemented(), + .attr(AddArenaTagAttr, ArenaTagType.TAILWIND, 4, true) + .target(MoveTarget.USER_SIDE), new StatusMove(Moves.ACUPRESSURE, Type.NORMAL, -1, 30, -1, 0, 4) .attr(StatChangeAttr, BattleStat.RAND, 2) .target(MoveTarget.USER_OR_NEAR_ALLY), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index a966a24303f..daa7876853b 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -589,6 +589,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ret *= 1.5; break; case Stat.SPD: + // Check both the player and enemy to see if Tailwind should be multiplying the speed of the Pokemon + if ((this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)) + || (!this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.ENEMY))) + ret *= 2; + if (this.getTag(BattlerTagType.SLOW_START)) ret >>= 1; if (this.status && this.status.effect === StatusEffect.PARALYSIS) From dffa9b2704dba212dfbaf1f1c518c4e65edb8737 Mon Sep 17 00:00:00 2001 From: maru Date: Thu, 2 May 2024 15:48:59 -0400 Subject: [PATCH 19/28] Add more files to be purged from CF cache on deploy --- .github/workflows/deploy.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e678a297852..07aed42a5a7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,4 +41,6 @@ jobs: files: | https://pokerogue.net/ https://pokerogue.net/index.html - https://pokerogue.net/manifest.json \ No newline at end of file + https://pokerogue.net/manifest.json + https://pokerogue.net/manifest.webmanifest + https://pokerogue.net/service-worker.js \ No newline at end of file From 991f097e9e2488192dd7a6d8084365e49aa9200b Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 17:48:08 -0400 Subject: [PATCH 20/28] Rebalance friendship and add starter friendship with candy reward --- src/data/pokemon-species.ts | 26 +++++++++++++++++++++++++- src/field/pokemon.ts | 27 +++++++++++++++++++++++++-- src/modifier/modifier-type.ts | 2 +- src/modifier/modifier.ts | 9 ++++----- src/phases.ts | 15 +++++---------- src/system/game-data.ts | 5 ++++- 6 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 2f8edefa403..c67f0c14b47 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -367,8 +367,8 @@ export abstract class PokemonSpeciesForm { loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise { return new Promise(resolve => { const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant); - scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`); scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant)); + scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`); scene.load.once(Phaser.Loader.Events.COMPLETE, () => { const originalWarn = console.warn; // Ignore warnings for missing frames, because there will be a lot @@ -3156,6 +3156,30 @@ export const noStarterFormKeys: string[] = [ SpeciesFormKey.ETERNAMAX ].map(k => k.toString()); +export function getStarterValueFriendshipCap(value: integer): integer { + switch (value) { + case 1: + return 20; + case 2: + return 40; + case 3: + return 60; + case 4: + return 100; + case 5: + return 140; + case 6: + return 200; + case 7: + return 280; + case 8: + case 9: + return 450; + default: + return 600; + } +} + export const starterPassiveAbilities = { [Species.BULBASAUR]: Abilities.SOLAR_POWER, [Species.CHARMANDER]: Abilities.INTIMIDATE, diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index daa7876853b..08482bbd914 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5,12 +5,12 @@ import { variantData } from '#app/data/variant'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move"; -import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, starterPassiveAbilities } from '../data/pokemon-species'; +import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; import { getLevelTotalExp } from '../data/exp'; import { Stat } from '../data/pokemon-stat'; -import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier'; +import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier'; import { PokeballType } from '../data/pokeball'; import { Gender } from '../data/gender'; import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims'; @@ -2367,6 +2367,29 @@ export class PlayerPokemon extends Pokemon { }, PartyUiHandler.FilterNonFainted); }); } + + addFriendship(friendship: integer): void { + const starterSpeciesId = this.species.getRootSpeciesId(); + const starterData = this.scene.gameData.starterData[starterSpeciesId]; + const amount = new Utils.IntegerHolder(friendship); + const starterAmount = new Utils.IntegerHolder(friendship * (this.scene.gameMode.isClassic ? 2 : 1)); + if (amount.value > 0) { + this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); + this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount); + + this.friendship = Math.min(this.friendship + amount.value, 255); + if (this.friendship === 255) + this.scene.validateAchv(achvs.MAX_FRIENDSHIP); + starterData.friendship = (starterData.friendship || 0) + starterAmount.value; + if (starterData.friendship >= getStarterValueFriendshipCap(speciesStarters[starterSpeciesId])) { + this.scene.gameData.addStarterCandy(getPokemonSpecies(starterSpeciesId), 1); + starterData.friendship = 0; + } + } else { + this.friendship = Math.max(this.friendship + amount.value, 0); + starterData.friendship = Math.max((starterData.friendship || 0) + starterAmount.value, 0); + } + } getPossibleEvolution(evolution: SpeciesFormEvolution): Promise { return new Promise(resolve => { diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 6237e8b5a50..4229b8be3b7 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1058,7 +1058,6 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10), new WeightedModifierType(modifierTypes.TM_ULTRA, 8), new WeightedModifierType(modifierTypes.RARER_CANDY, 4), - new WeightedModifierType(modifierTypes.SOOTHE_BELL, (party: Pokemon[]) => party.find(p => (pokemonEvolutions.hasOwnProperty(p.species.speciesId) && pokemonEvolutions[p.species.speciesId].find(e => e.condition && e.condition instanceof SpeciesFriendshipEvolutionCondition)) || p.moveset.find(m => m.moveId === Moves.RETURN)) ? 16 : 0, 16), new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, 2), new WeightedModifierType(modifierTypes.IV_SCANNER, 4), new WeightedModifierType(modifierTypes.EXP_CHARM, 8), @@ -1078,6 +1077,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.BATON, 2), new WeightedModifierType(modifierTypes.SOUL_DEW, 8), //new WeightedModifierType(modifierTypes.OVAL_CHARM, 6), + new WeightedModifierType(modifierTypes.SOOTHE_BELL, 4), new WeightedModifierType(modifierTypes.ABILITY_CHARM, 6), new WeightedModifierType(modifierTypes.FOCUS_BAND, 5), new WeightedModifierType(modifierTypes.KINGS_ROCK, 3), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index d8fad1466b9..88b009d3a48 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1111,9 +1111,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier { pokemon.levelExp = 0; } - const friendshipIncrease = new Utils.IntegerHolder(5); - pokemon.scene.applyModifier(PokemonFriendshipBoosterModifier, true, pokemon, friendshipIncrease); - pokemon.friendship = Math.min(pokemon.friendship + friendshipIncrease.value, 255); + pokemon.addFriendship(5); pokemon.scene.unshiftPhase(new LevelUpPhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), pokemon.level - levelCount.value, pokemon.level)); @@ -1392,13 +1390,14 @@ export class PokemonFriendshipBoosterModifier extends PokemonHeldItemModifier { } apply(args: any[]): boolean { - (args[1] as Utils.IntegerHolder).value *= 1 + 0.5 * this.getStackCount(); + const friendship = args[1] as Utils.IntegerHolder; + friendship.value = Math.floor(friendship.value * (1 + 0.5 * this.getStackCount())); return true; } getMaxHeldItemCount(pokemon: Pokemon): integer { - return 5; + return 3; } } diff --git a/src/phases.ts b/src/phases.ts index 2ffa25aef0f..4c2f5536268 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -6,7 +6,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; -import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, PokemonFriendshipBoosterModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; +import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; @@ -3154,8 +3154,8 @@ export class FaintPhase extends PokemonPhase { this.scene.getField(true).filter(p => p !== pokemon).forEach(p => p.removeTagsBySourceId(pokemon.id)); pokemon.faintCry(() => { - const friendshipDecrease = new Utils.IntegerHolder(10); - pokemon.friendship = Math.max(pokemon.friendship - friendshipDecrease.value, 0); + if (pokemon instanceof PlayerPokemon) + pokemon.addFriendship(-10); pokemon.hideInfo(); this.scene.playSound('faint'); this.scene.tweens.add({ @@ -3226,13 +3226,8 @@ export class VictoryPhase extends PokemonPhase { for (let partyMember of expPartyMembers) { const pId = partyMember.id; const participated = participantIds.has(pId); - if (participated) { - const friendshipIncrease = new Utils.IntegerHolder(2); - this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, partyMember, friendshipIncrease); - partyMember.friendship = Math.min(partyMember.friendship + friendshipIncrease.value, 255); - if (partyMember.friendship === 255) - this.scene.validateAchv(achvs.MAX_FRIENDSHIP); - } + if (participated) + partyMember.addFriendship(2); else if (!expShareModifier) { partyMemberExp.push(0); continue; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index e11c2dcc572..b7495a1eac9 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -169,6 +169,7 @@ export interface StarterDataEntry { moveset: StarterMoveset | StarterFormMoveData; eggMoves: integer; candyCount: integer; + friendship: integer; abilityAttr: integer; passiveAttr: integer; valueReduction: integer; @@ -988,6 +989,7 @@ export class GameData { moveset: null, eggMoves: 0, candyCount: 0, + friendship: 0, abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0, passiveAttr: 0, valueReduction: 0 @@ -1035,6 +1037,7 @@ export class GameData { const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId); const newCatch = !caughtAttr; + const hasNewAttr = (caughtAttr & dexAttr) !== dexAttr; if (incrementCount) { if (!fromEgg) { @@ -1057,7 +1060,7 @@ export class GameData { this.gameStats.shinyPokemonHatched++; } - if (!hasPrevolution) + if (!hasPrevolution && (!pokemon.scene.gameMode.isDaily || hasNewAttr)) this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * Math.pow(2, pokemon.variant || 0) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1)); } From fec87718300aa5d0bd56f1679ed853815316a33d Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Thu, 2 May 2024 16:49:22 -0500 Subject: [PATCH 21/28] Fix Shedinja Luck and Crash Shedinja wasn't taking the luck value from Ninjask so when it calculated its luck it just took the entire fused Pokemon's luck somehow. This has been fixed so it takes both the first and second part of the fusion's luck values instead. Also fixes an issue where Shedinja crashed the game if it was the second part of a fusion combo. Now the correct pokemon species gets checked against and the correct pokemon evolution occurs to create Shedinja. --- src/field/pokemon.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 08482bbd914..c5036ce72c6 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2457,12 +2457,17 @@ export class PlayerPokemon extends Pokemon { private handleSpecialEvolutions(evolution: SpeciesFormEvolution) { const isFusion = evolution instanceof FusionSpeciesFormEvolution; - if ((!isFusion ? this.species : this.fusionSpecies).speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) { - const newEvolution = pokemonEvolutions[this.species.speciesId][1]; + + const evoSpecies = (!isFusion ? this.species : this.fusionSpecies) + if (evoSpecies.speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) { + const newEvolution = pokemonEvolutions[evoSpecies.speciesId][1]; + if (newEvolution.condition.predicate(this)) { const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature); newPokemon.natureOverride = this.natureOverride; newPokemon.moveset = this.moveset.slice(); + newPokemon.luck = this.luck; + newPokemon.fusionSpecies = this.fusionSpecies; newPokemon.fusionFormIndex = this.fusionFormIndex; newPokemon.fusionAbilityIndex = this.fusionAbilityIndex; @@ -2470,8 +2475,9 @@ export class PlayerPokemon extends Pokemon { newPokemon.fusionVariant = this.fusionVariant; newPokemon.fusionGender = this.fusionGender; newPokemon.fusionLuck = this.fusionLuck; + this.scene.getParty().push(newPokemon); - newPokemon.evolve(newEvolution); + newPokemon.evolve(!isFusion ? newEvolution : new FusionSpeciesFormEvolution(this.id, newEvolution)); const modifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === this.id, true) as PokemonHeldItemModifier[]; modifiers.forEach(m => { From 67431fb83b82d45cc98f59a324a3a8ecbd7fb7ff Mon Sep 17 00:00:00 2001 From: Simoninoo <105045724+Simoninoo@users.noreply.github.com> Date: Fri, 3 May 2024 02:45:45 +0200 Subject: [PATCH 22/28] Patch Ita (#399) * Syntax correction * Tutorial translation --- src/locales/it/pokemon-stat.ts | 2 +- src/locales/it/tutorial.ts | 62 +++++++++++++++++----------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/locales/it/pokemon-stat.ts b/src/locales/it/pokemon-stat.ts index a3a62edebe2..b2c023aa383 100644 --- a/src/locales/it/pokemon-stat.ts +++ b/src/locales/it/pokemon-stat.ts @@ -5,7 +5,7 @@ export const pokemonStat: SimpleTranslationEntries = { "HPshortened": "PS", "ATK": "Attacco", "ATKshortened": "Att", - "DEF": "Difensa", + "DEF": "Difesa", "DEFshortened": "Dif", "SPATK": "Att. Sp.", "SPATKshortened": "AttSp", diff --git a/src/locales/it/tutorial.ts b/src/locales/it/tutorial.ts index 2773b6710ba..898dcead8a4 100644 --- a/src/locales/it/tutorial.ts +++ b/src/locales/it/tutorial.ts @@ -1,42 +1,42 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const tutorial: SimpleTranslationEntries = { - "intro": `Welcome to PokéRogue! This is a battle-focused Pokémon fangame with roguelite elements. - $This game is not monetized and we claim no ownership of Pokémon nor of the copyrighted assets used. - $The game is a work in progress, but fully playable.\nFor bug reports, please use the Discord community. - $If the game runs slowly, please ensure 'Hardware Acceleration' is turned on in your browser settings.`, + "intro": `Benvenuto in PokéRogue! Questo gioco si concentra sulle battaglie, con elementi roguelite. + $Questo gioco non è monetizzato e non siamo proprietari di Pokemon e Assets presenti nel gioco. + $Il gioco è work-in-progress ma giocabile al 100%.\nPer reportare eventuali bugs è possibile discuterne sul nostro Discord. + $Se il game risulta 'lento', assicurati di aver abilitato l'Accelerazione Hardware nelle impostazioni del tuo Browser`, - "accessMenu": `To access the menu, press M or Escape while awaiting input.\nThe menu contains settings and various features.`, + "accessMenu": `Per accedere al menù, press M o Esc.\nDal menù puoi cambiare impostazioni, controllare la wiki e accedere a varie features.`, - "menu": `From this menu you can access the settings. - $From the settings you can change game speed, window style, and other options. - $There are also various other features here, so be sure to check them all!`, + "menu": `Da questo menù puoi accedere alle impostazioni. + $Dalle impostazioni puoi cambiare velocità di gioco, stile di finestra e altre opzioni. + $Ci sono varie funzionalità, controlla bene e non perderti nulla!`, - "starterSelect": `From this screen, you can select your starters.\nThese are your initial party members. - $Each starter has a value. Your party can have up to\n6 members as long as the total does not exceed 10. - $You can also select gender, ability, and form depending on\nthe variants you've caught or hatched. - $The IVs for a species are also the best of every one you've\ncaught or hatched, so try to get lots of the same species!`, + "starterSelect": `Da questa schermata puoi selezionare il tuo starter.\nQuesti sono i membri iniziali del tuo parti. + $Ogni starter ha un valore. Puoi avere fino a \n6 Pokèmon, avendo a disposizione un massimo di 10 punti. + $Puoi anche selezionare Sesso, Abilità, e Forma a seconda delle\nvarianti che hai catturato o schiuso. + $Le IVs di una specie sono le migliori rispetto a tutte quelle che hai\ncatturato o schiuso, quindi prova a catturarne il piu possibile!`, - "pokerus": `A daily random 3 selectable starters have a purple border. - $If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, + "pokerus": `Giornalmente 3 Starter casuali disponibili avranno il bordo viola. + $Se possiedi uno di questi starter,\nprova ad aggiungerlo al party. Ricorda di controllare le info!`, - "statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. - $Your Pokémon are recalled before a trainer battle and before entering a new biome. - $You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, + "statChange": `I cambiamenti alle statistiche persistono fintanto che i tuoi pokèmon resteranno in campo. + $I tuoi pokemon verranno richiamati quando incontrerai un allenatore o al cambiamento di bioma. + $Puoi anche vedere i cambiamenti alle statistiche in corso tenendo premuto C o Shift`, - "selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. - $These range from consumables, to Pokémon held items, to passive permanent items. - $Most non-consumable item effects will stack in various ways. - $Some items will only show up if they can be used, such as evolution items. - $You can also transfer held items between Pokémon using the transfer option. - $The transfer option will appear in the bottom right once you have obtained a held item. - $You may purchase consumable items with money, and a larger variety will be available the further you get. - $Be sure to buy these before you pick your random item, as it will progress to the next battle once you do.`, + "selectItem": `Dopo ogni battaglia avrai disponibili tre item.\nPotrai prenderne solo uno. + $Questi spaziano tra consumabili, item tenuti da Pokèmon o con un effetto passivo permanente. + $La maggior parte degli Item non Consumabili possono stackare in diversi modi. + $Alcuni Item risulteranno disponibili solo se possono essere usati, come Item Evolutivi. + $Puoi anche passare un Item tenuto da un Pokèmon ad un altro attraverso l'opzione 'trasferisci strumento'. + $L'opzione 'trasferisci strumento' sarà disponibile solo dopo aver assegnato uno strumento ad un Pokèmon. + $Puoi acquistare consumabili con le monete, progredendo saranno poi disponibili ulteriori oggetti. + $Assicurati di fare un acquisto prima di selezionare un item casuale, poichè passerai subito alla lotta successiva.`, - "eggGacha": `From this screen, you can redeem your vouchers for\nPokémon eggs. - $Eggs have to be hatched and get closer to hatching after\nevery battle. Rarer eggs take longer to hatch. - $Hatched Pokémon also won't be added to your party, they will\nbe added to your starters. - $Pokémon hatched from eggs generally have better IVs than\nwild Pokémon. - $Some Pokémon can only even be obtained from eggs. - $There are 3 different machines to pull from with different\nbonuses, so pick the one that suits you best!`, + "eggGacha": `Da questa schermata, puoi riscattare i tuoi vouchers in cambio di\nuova Pokèmon. + $Le uova vanno schiuse e saranno sempre più vicine alla schiusura dopo\nogni battaglia. Le uova più rare impiegheranno più battaglie per la schiusura. + $I Pokémon schiusi non verranno aggiunti alla tua squadra, saranno\naggiunti ai tuoi starters. + $I Pokémon schiusi generalmente hanno IVs migliori rispetto ai\n Pokémon selvatici. + $Alcuni Pokémon possono essere ottenuti solo tramite uova. + $Ci sono 3 diversi macchinari con differenti\nbonus, scegli quello che preferisci!`, } as const; \ No newline at end of file From b30ab6136e8df4c792420d1c0e7f3777ca984330 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Thu, 2 May 2024 21:55:11 -0400 Subject: [PATCH 23/28] Starter friendship for candies is split between spliced species --- src/field/pokemon.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index c5036ce72c6..7720d741b20 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -37,7 +37,7 @@ import PartyUiHandler, { PartyOption, PartyUiMode } from '../ui/party-ui-handler import SoundFade from 'phaser3-rex-plugins/plugins/soundfade'; import { LevelMoves } from '../data/pokemon-level-moves'; import { DamageAchv, achvs } from '../system/achv'; -import { DexAttr, StarterMoveset } from '../system/game-data'; +import { DexAttr, StarterDataEntry, StarterMoveset } from '../system/game-data'; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from '@material/material-color-utilities'; import { Nature, getNatureStatMultiplier } from '../data/nature'; import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from '../data/pokemon-forms'; @@ -2370,9 +2370,13 @@ export class PlayerPokemon extends Pokemon { addFriendship(friendship: integer): void { const starterSpeciesId = this.species.getRootSpeciesId(); - const starterData = this.scene.gameData.starterData[starterSpeciesId]; + const fusionStarterSpeciesId = this.isFusion() ? this.fusionSpecies.getRootSpeciesId() : 0; + const starterData = [ + this.scene.gameData.starterData[starterSpeciesId], + fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null + ].filter(d => d); const amount = new Utils.IntegerHolder(friendship); - const starterAmount = new Utils.IntegerHolder(friendship * (this.scene.gameMode.isClassic ? 2 : 1)); + const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic ? 2 : 1) / (fusionStarterSpeciesId ? 2 : 1))); if (amount.value > 0) { this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount); @@ -2380,14 +2384,18 @@ export class PlayerPokemon extends Pokemon { this.friendship = Math.min(this.friendship + amount.value, 255); if (this.friendship === 255) this.scene.validateAchv(achvs.MAX_FRIENDSHIP); - starterData.friendship = (starterData.friendship || 0) + starterAmount.value; - if (starterData.friendship >= getStarterValueFriendshipCap(speciesStarters[starterSpeciesId])) { - this.scene.gameData.addStarterCandy(getPokemonSpecies(starterSpeciesId), 1); - starterData.friendship = 0; - } + starterData.forEach((sd: StarterDataEntry, i: integer) => { + const speciesId = !i ? starterSpeciesId : fusionStarterSpeciesId as Species; + sd.friendship = (sd.friendship || 0) + starterAmount.value; + if (sd.friendship >= getStarterValueFriendshipCap(speciesStarters[speciesId])) { + this.scene.gameData.addStarterCandy(getPokemonSpecies(speciesId), 1); + sd.friendship = 0; + } + }); } else { this.friendship = Math.max(this.friendship + amount.value, 0); - starterData.friendship = Math.max((starterData.friendship || 0) + starterAmount.value, 0); + for (let sd of starterData) + sd.friendship = Math.max((sd.friendship || 0) + starterAmount.value, 0); } } From 60117947322354f51801e01d295d9657bae1af66 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Thu, 2 May 2024 21:58:38 -0500 Subject: [PATCH 24/28] Minor egg move fix Gen 8 fossils unintentionally had Earthquake. They have now been replaced. --- src/data/egg-moves.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/egg-moves.ts b/src/data/egg-moves.ts index 800c9a0ef25..221496a177d 100644 --- a/src/data/egg-moves.ts +++ b/src/data/egg-moves.ts @@ -458,9 +458,9 @@ export const speciesEggMoves = { [Species.MORPEKO]: [ Moves.TRIPLE_AXEL, Moves.OBSTRUCT, Moves.PARTING_SHOT, Moves.SWORDS_DANCE ], [Species.CUFANT]: [ Moves.LIQUIDATION, Moves.HEAVY_SLAM, Moves.CLOSE_COMBAT, Moves.GIGATON_HAMMER ], [Species.DRACOZOLT]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.FIRE_LASH, Moves.DRAGON_DANCE ], - [Species.ARCTOZOLT]: [ Moves.TRIPLE_AXEL, Moves.EARTHQUAKE, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], + [Species.ARCTOZOLT]: [ Moves.TRIPLE_AXEL, Moves.LIQUIDATION, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], [Species.DRACOVISH]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.THUNDER_FANG, Moves.DRAGON_DANCE ], - [Species.ARCTOVISH]: [ Moves.TRIPLE_AXEL, Moves.EARTHQUAKE, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], + [Species.ARCTOVISH]: [ Moves.TRIPLE_AXEL, Moves.SUPERCELL_SLAM, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], [Species.DURALUDON]: [ Moves.CALM_MIND, Moves.BODY_PRESS, Moves.EARTH_POWER, Moves.RECOVER ], [Species.DREEPY]: [ Moves.DRAGON_ENERGY, Moves.SHED_TAIL, Moves.BLAZING_TORQUE, Moves.SPECTRAL_THIEF ], [Species.ZACIAN]: [ Moves.MAGICAL_TORQUE, Moves.BITTER_BLADE, Moves.LEAF_BLADE, Moves.VICTORY_DANCE ], From fbc08005715ac1b1bdb4a3e38e6bf468ad3625e7 Mon Sep 17 00:00:00 2001 From: Matt Ross <13306707+mattrossdev@users.noreply.github.com> Date: Thu, 2 May 2024 22:20:41 -0700 Subject: [PATCH 25/28] Issue/smack down should cancel fly (#407) * Smack down and thousand arrows should cancel charging fly * Remove console log * Update interruptible check to use flying tag instead of move history * Remove extra comma --- src/data/battler-tags.ts | 25 +++++++++++++++++++++++++ src/data/enums/battler-tag-type.ts | 1 + src/data/move.ts | 4 ++++ src/phases.ts | 2 +- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index aaab9f9a4a2..2521a0e03c5 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -163,6 +163,29 @@ export class FlinchedTag extends BattlerTag { } } +export class InterruptedTag extends BattlerTag { + constructor(sourceMove: Moves){ + super(BattlerTagType.INTERRUPTED, BattlerTagLapseType.PRE_MOVE, 0, sourceMove) + } + + canAdd(pokemon: Pokemon): boolean { + return !!pokemon.getTag(BattlerTagType.FLYING) + } + + onAdd(pokemon: Pokemon): void { + super.onAdd(pokemon); + + pokemon.getMoveQueue().shift() + pokemon.pushMoveHistory({move: Moves.NONE, result: MoveResult.OTHER}) + } + + lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { + super.lapse(pokemon, lapseType); + (pokemon.scene.getCurrentPhase() as MovePhase).cancel(); + return true + } +} + export class ConfusedTag extends BattlerTag { constructor(turnCount: integer, sourceMove: Moves) { super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove); @@ -1081,6 +1104,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new RechargingTag(sourceMove); case BattlerTagType.FLINCHED: return new FlinchedTag(sourceMove); + case BattlerTagType.INTERRUPTED: + return new InterruptedTag(sourceMove); case BattlerTagType.CONFUSED: return new ConfusedTag(turnCount, sourceMove); case BattlerTagType.INFATUATED: diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index 4d810b737aa..f76e5526f7e 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -3,6 +3,7 @@ export enum BattlerTagType { NONE = "NONE", RECHARGING = "RECHARGING", FLINCHED = "FLINCHED", + INTERRUPTED = "INTERRUPTED", CONFUSED = "CONFUSED", INFATUATED = "INFATUATED", SEEDED = "SEEDED", diff --git a/src/data/move.ts b/src/data/move.ts index b26af03fc5e..a227c522a86 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -5106,6 +5106,8 @@ export function initMoves() { .unimplemented(), new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5) + .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) + .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING]) .attr(HitsTagAttr, BattlerTagType.FLYING, false) .makesContact(false), new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5) @@ -5469,6 +5471,8 @@ export function initMoves() { new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, 100, 0, 6) .attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(HitsTagAttr, BattlerTagType.FLYING, false) + .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) + .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING]) .makesContact(false) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) diff --git a/src/phases.ts b/src/phases.ts index 4c2f5536268..40ab1f30637 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2333,7 +2333,7 @@ export class MovePhase extends BattlePhase { return; } - if (this.pokemon.getTag(BattlerTagType.RECHARGING)) + if (this.pokemon.getTag(BattlerTagType.RECHARGING|| BattlerTagType.INTERRUPTED)) return; this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500); From f7b391746ed0076f2c548dd6836f5f8dc40c5265 Mon Sep 17 00:00:00 2001 From: Jaime Date: Fri, 3 May 2024 13:29:22 +0200 Subject: [PATCH 26/28] Fix Gyro Ball only checking base stat --- src/data/move.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index a227c522a86..ea89788cf93 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1770,13 +1770,13 @@ export class BattleStatRatioPowerAttr extends VariablePowerAttr { if (this.invert) { // Gyro ball uses a specific formula - let userSpeed = user.getStat(this.stat); + let userSpeed = user.getBattleStat(this.stat); if (userSpeed < 1) { // Gen 6+ always have 1 base power power.value = 1; return true; } - let bp = Math.floor(Math.min(150, 25 * target.getStat(this.stat) / userSpeed + 1)); + let bp = Math.floor(Math.min(150, 25 * target.getBattleStat(this.stat) / userSpeed + 1)); power.value = bp; return true; } From b84a4b4ee5fde701464383c271e67fea0248f38f Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Fri, 3 May 2024 01:46:19 -0500 Subject: [PATCH 27/28] Fix Shedinja PPused Share Fixed having Shedinja share PP usage with the Ninjask it evolved from and vice versa. The solution was to make a deep copy of each move in the moveset array rather than copying the array itself. --- src/field/pokemon.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 7720d741b20..bc51323075b 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2473,7 +2473,7 @@ export class PlayerPokemon extends Pokemon { if (newEvolution.condition.predicate(this)) { const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature); newPokemon.natureOverride = this.natureOverride; - newPokemon.moveset = this.moveset.slice(); + newPokemon.moveset = this.copyMoveset(); newPokemon.luck = this.luck; newPokemon.fusionSpecies = this.fusionSpecies; @@ -2583,6 +2583,15 @@ export class PlayerPokemon extends Pokemon { this.updateFusionPalette(); }); } + + /** Returns a deep copy of this Pokemon's moveset array */ + copyMoveset(): PokemonMove[] { + let newMoveset = []; + this.moveset.forEach(move => + newMoveset.push(new PokemonMove(move.moveId, 0, move.ppUp, move.virtual))); + + return newMoveset; + } } export class EnemyPokemon extends Pokemon { From 24a9dba2c46e70fb2d06b87dec7dec952dc98686 Mon Sep 17 00:00:00 2001 From: Paul Beslin Date: Fri, 3 May 2024 00:18:05 +0200 Subject: [PATCH 28/28] Fix attacks with charge (solar beam, dig...) allowing to switch target on second turn --- src/data/battler-tags.ts | 8 ++++++++ src/data/enums/battler-tag-type.ts | 1 + src/data/move.ts | 5 ++++- src/phases.ts | 9 ++++++--- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 2521a0e03c5..8ff684394ec 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -391,6 +391,12 @@ export class FrenzyTag extends BattlerTag { } } +export class ChargingTag extends BattlerTag { + constructor(sourceMove: Moves, sourceId: integer) { + super(BattlerTagType.CHARGING, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId); + } +} + export class EncoreTag extends BattlerTag { public moveId: Moves; @@ -1116,6 +1122,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new NightmareTag(); case BattlerTagType.FRENZY: return new FrenzyTag(sourceMove, sourceId); + case BattlerTagType.CHARGING: + return new ChargingTag(sourceMove, sourceId); case BattlerTagType.ENCORE: return new EncoreTag(sourceId); case BattlerTagType.HELPING_HAND: diff --git a/src/data/enums/battler-tag-type.ts b/src/data/enums/battler-tag-type.ts index f76e5526f7e..7a9f6ba8bb2 100644 --- a/src/data/enums/battler-tag-type.ts +++ b/src/data/enums/battler-tag-type.ts @@ -9,6 +9,7 @@ export enum BattlerTagType { SEEDED = "SEEDED", NIGHTMARE = "NIGHTMARE", FRENZY = "FRENZY", + CHARGING = "CHARGING", ENCORE = "ENCORE", HELPING_HAND = "HELPING_HAND", INGRAIN = "INGRAIN", diff --git a/src/data/move.ts b/src/data/move.ts index ea89788cf93..21f376254f7 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1325,10 +1325,13 @@ export class ChargeAttr extends OverrideMoveEffectAttr { user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true }); if (this.sameTurn) user.scene.pushMovePhase(new MovePhase(user.scene, user, [ target.getBattlerIndex() ], user.moveset.find(m => m.moveId === move.id), true), this.followUpPriority); + user.addTag(BattlerTagType.CHARGING, 1, move.id, user.id); resolve(true); }); - } else + } else { + user.lapseTag(BattlerTagType.CHARGING); resolve(false); + } }); } diff --git a/src/phases.ts b/src/phases.ts index 40ab1f30637..e4ed8d2938c 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1686,6 +1686,8 @@ export class CommandPhase extends FieldPhase { console.log(moveTargets, playerPokemon.name); if (moveTargets.targets.length <= 1 || moveTargets.multiple) turnCommand.move.targets = moveTargets.targets; + else if(playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) + turnCommand.move.targets = playerPokemon.getMoveQueue()[0].targets; else this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand; @@ -2327,13 +2329,14 @@ export class MovePhase extends BattlePhase { showMoveText(): void { if (this.move.getMove().getAttrs(ChargeAttr).length) { - this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500); const lastMove = this.pokemon.getLastXMoves() as TurnMove[]; - if (!lastMove.length || lastMove[0].move !== this.move.getMove().id || lastMove[0].result !== MoveResult.OTHER) + if (!lastMove.length || lastMove[0].move !== this.move.getMove().id || lastMove[0].result !== MoveResult.OTHER){ + this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500); return; + } } - if (this.pokemon.getTag(BattlerTagType.RECHARGING|| BattlerTagType.INTERRUPTED)) + if (this.pokemon.getTag(BattlerTagType.RECHARGING || BattlerTagType.INTERRUPTED)) return; this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500);