From 9a49691a9e906f80fb088d3240319d2647456650 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Mon, 13 May 2024 13:10:01 -0400 Subject: [PATCH 01/27] Add max options to language select Add max options to language select (fixes #819) --- src/system/settings.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/system/settings.ts b/src/system/settings.ts index 08f9de0f812..15c1f19aa04 100644 --- a/src/system/settings.ts +++ b/src/system/settings.ts @@ -206,19 +206,20 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer) label: 'Deutsch', handler: () => changeLocaleHandler('de') }, - { - label: '简体中文', - handler: () => changeLocaleHandler('zh_CN') - }, { label: 'Português (BR)', handler: () => changeLocaleHandler('pt_BR') }, + { + label: '简体中文', + handler: () => changeLocaleHandler('zh_CN') + }, { label: 'Cancel', handler: () => cancelHandler() } - ] + ], + maxOptions: 7 }); return false; } From 34a4f86982e33066ab240d0191589759f1cd4e7a Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Mon, 13 May 2024 12:50:56 -0500 Subject: [PATCH 02/27] Add a couple starter select localization entries The passive ability's "Locked" and "Disabled" strings can now be localized. --- src/locales/de/starter-select-ui-handler.ts | 4 +++- src/locales/en/starter-select-ui-handler.ts | 4 +++- src/locales/es/starter-select-ui-handler.ts | 4 +++- src/locales/fr/starter-select-ui-handler.ts | 4 +++- src/locales/it/starter-select-ui-handler.ts | 4 +++- src/locales/pt_BR/starter-select-ui-handler.ts | 4 +++- src/locales/zh_CN/starter-select-ui-handler.ts | 4 +++- src/ui/starter-select-ui-handler.ts | 2 +- 8 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/locales/de/starter-select-ui-handler.ts b/src/locales/de/starter-select-ui-handler.ts index a982f30d84a..5ee3da9db0d 100644 --- a/src/locales/de/starter-select-ui-handler.ts +++ b/src/locales/de/starter-select-ui-handler.ts @@ -28,5 +28,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleNature": "N: Wesen Ändern", "cycleVariant": "V: Seltenheit ändern", "enablePassive": "Passiv-Skill aktivieren", - "disablePassive": "Passiv-Skill deaktivieren" + "disablePassive": "Passiv-Skill deaktivieren", + "locked": "Locked", + "disabled": "Disabled" } \ No newline at end of file diff --git a/src/locales/en/starter-select-ui-handler.ts b/src/locales/en/starter-select-ui-handler.ts index c7595cb2f95..dd3904e121b 100644 --- a/src/locales/en/starter-select-ui-handler.ts +++ b/src/locales/en/starter-select-ui-handler.ts @@ -28,5 +28,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleNature": 'N: Cycle Nature', "cycleVariant": 'V: Cycle Variant', "enablePassive": "Enable Passive", - "disablePassive": "Disable Passive" + "disablePassive": "Disable Passive", + "locked": "Locked", + "disabled": "Disabled" } \ No newline at end of file diff --git a/src/locales/es/starter-select-ui-handler.ts b/src/locales/es/starter-select-ui-handler.ts index 629e2563260..e8cd9bce0de 100644 --- a/src/locales/es/starter-select-ui-handler.ts +++ b/src/locales/es/starter-select-ui-handler.ts @@ -28,5 +28,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleNature": 'N: Cambiar Naturaleza', "cycleVariant": 'V: Cambiar Variante', "enablePassive": "Activar Pasiva", - "disablePassive": "Desactivar Pasiva" + "disablePassive": "Desactivar Pasiva", + "locked": "Locked", + "disabled": "Disabled" } \ No newline at end of file diff --git a/src/locales/fr/starter-select-ui-handler.ts b/src/locales/fr/starter-select-ui-handler.ts index 77a79387ac6..3a8bb2e653b 100644 --- a/src/locales/fr/starter-select-ui-handler.ts +++ b/src/locales/fr/starter-select-ui-handler.ts @@ -28,5 +28,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleNature": "N: » Natures", "cycleVariant": "V: » Variants", "enablePassive": "Activer Passif", - "disablePassive": "Désactiver Passif" + "disablePassive": "Désactiver Passif", + "locked": "Locked", + "disabled": "Disabled" } diff --git a/src/locales/it/starter-select-ui-handler.ts b/src/locales/it/starter-select-ui-handler.ts index 1a442ffe9d9..e8c58ad138d 100644 --- a/src/locales/it/starter-select-ui-handler.ts +++ b/src/locales/it/starter-select-ui-handler.ts @@ -28,5 +28,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleNature": 'N: Alterna Natura', "cycleVariant": 'V: Alterna Variante', "enablePassive": "Attiva Passiva", - "disablePassive": "Disattiva Passiva" + "disablePassive": "Disattiva Passiva", + "locked": "Locked", + "disabled": "Disabled" } \ No newline at end of file diff --git a/src/locales/pt_BR/starter-select-ui-handler.ts b/src/locales/pt_BR/starter-select-ui-handler.ts index 2932768b591..4877c169141 100644 --- a/src/locales/pt_BR/starter-select-ui-handler.ts +++ b/src/locales/pt_BR/starter-select-ui-handler.ts @@ -28,5 +28,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleNature": 'N: Mudar Nature', "cycleVariant": 'V: Mudar Variante', "enablePassive": "Ativar Passiva", - "disablePassive": "Desativar Passiva" + "disablePassive": "Desativar Passiva", + "locked": "Locked", + "disabled": "Disabled" } \ No newline at end of file diff --git a/src/locales/zh_CN/starter-select-ui-handler.ts b/src/locales/zh_CN/starter-select-ui-handler.ts index 9d3a076e55d..c2d0a82d837 100644 --- a/src/locales/zh_CN/starter-select-ui-handler.ts +++ b/src/locales/zh_CN/starter-select-ui-handler.ts @@ -28,5 +28,7 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleNature": 'N: 切换性格', "cycleVariant": 'V: 切换变种', "enablePassive": "启用被动", - "disablePassive": "禁用被动" + "disablePassive": "禁用被动", + "locked": "Locked", + "disabled": "Disabled" } \ No newline at end of file diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 2f33481d6f1..148600b8d31 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -1580,7 +1580,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonAbilityText.setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true)); const passiveAttr = this.scene.gameData.starterData[species.speciesId].passiveAttr; - this.pokemonPassiveText.setText(passiveAttr & PassiveAttr.UNLOCKED ? passiveAttr & PassiveAttr.ENABLED ? allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name : 'Disabled' : 'Locked'); + this.pokemonPassiveText.setText(passiveAttr & PassiveAttr.UNLOCKED ? passiveAttr & PassiveAttr.ENABLED ? allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name : i18next.t("starterSelectUiHandler:disabled") : i18next.t("starterSelectUiHandler:locked")); this.pokemonPassiveText.setColor(this.getTextColor(passiveAttr === (PassiveAttr.UNLOCKED | PassiveAttr.ENABLED) ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GRAY)); this.pokemonPassiveText.setShadowColor(this.getTextColor(passiveAttr === (PassiveAttr.UNLOCKED | PassiveAttr.ENABLED) ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GRAY, true)); From 610de916a02268f8b245d893ab2ce15843d7faca Mon Sep 17 00:00:00 2001 From: Lugiad Date: Mon, 13 May 2024 20:01:30 +0200 Subject: [PATCH 03/27] Update French starter-select-ui-handler.ts (#821) --- src/locales/fr/starter-select-ui-handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/locales/fr/starter-select-ui-handler.ts b/src/locales/fr/starter-select-ui-handler.ts index 3a8bb2e653b..9f4309e40f4 100644 --- a/src/locales/fr/starter-select-ui-handler.ts +++ b/src/locales/fr/starter-select-ui-handler.ts @@ -29,6 +29,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleVariant": "V: » Variants", "enablePassive": "Activer Passif", "disablePassive": "Désactiver Passif", - "locked": "Locked", - "disabled": "Disabled" + "locked": "Verrouillé", + "disabled": "Désactivé" } From fa60e002e89c6d5d5da2f451ac4370aeffb758b6 Mon Sep 17 00:00:00 2001 From: Matt Ross <13306707+mattrossdev@users.noreply.github.com> Date: Mon, 13 May 2024 11:05:09 -0700 Subject: [PATCH 04/27] Fixes some variable damage moves not working with tinted lens (#759) * Fixes some variable damage moves not working with abilities * Rework as new ability attribute * Update variable base power check to original location * formatting * Add tsdoc comments * add floor for potential non int multipliers * Update pokemon.ts --------- Co-authored-by: Benjamin Odom --- src/data/ability.ts | 38 +++++++++++++++++++++++++++++++++++++- src/field/pokemon.ts | 5 ++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 662cd3715eb..fee574e4a5e 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -991,6 +991,42 @@ export class MoveTypeChangeAttr extends PreAttackAbAttr { } } +/** + * Class for abilities that boost the damage of moves + * For abilities that boost the base power of moves, see VariableMovePowerAbAttr + * @param damageMultiplier the amount to multiply the damage by + * @param condition the condition for this ability to be applied + */ +export class DamageBoostAbAttr extends PreAttackAbAttr { + private damageMultiplier: number; + private condition: PokemonAttackCondition; + + constructor(damageMultiplier: number, condition: PokemonAttackCondition){ + super(true); + this.damageMultiplier = damageMultiplier; + this.condition = condition; + } + + /** + * + * @param pokemon the attacker pokemon + * @param passive N/A + * @param defender the target pokemon + * @param move the move used by the attacker pokemon + * @param args Utils.NumberHolder as damage + * @returns true if the function succeeds + */ + applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { + if (this.condition(pokemon, defender, move.getMove())) { + const power = args[0] as Utils.NumberHolder; + power.value = Math.floor(power.value * this.damageMultiplier); + return true; + } + + return false; + } +} + export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr { private condition: PokemonAttackCondition; private powerMultiplier: number; @@ -3121,7 +3157,7 @@ export function initAbilities() { .attr(IgnoreOpponentStatChangesAbAttr) .ignorable(), new Ability(Abilities.TINTED_LENS, 4) - .attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) <= 0.5, 2), + .attr(DamageBoostAbAttr, 2, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) <= 0.5), new Ability(Abilities.FILTER, 4) .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 0.75) .ignorable(), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 807be3f8d9d..307f98f2f2d 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -1545,6 +1545,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!burnDamageReductionCancelled.value) damage.value = Math.floor(damage.value / 2); } + + applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, battlerMove, damage); + move.getAttrs(HitsTagAttr).map(hta => hta as HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => { if (this.getTag(hta.tagType)) damage.value *= 2; From 4e6cf2a6aced2e5d23c4fbe74e03574db7f91431 Mon Sep 17 00:00:00 2001 From: Matt Ross <13306707+mattrossdev@users.noreply.github.com> Date: Mon, 13 May 2024 11:06:15 -0700 Subject: [PATCH 05/27] Facade should ignore burn damage reduction (#530) * Facade should ignore burn damage reduction * update order of burn conditions * remove unnecessary space * undo facade check in apply * Rework facade bypassing burn as move attribute * Only check ability attribute if move attribute was false * Add missing semicolon * Add tsdoc comment * Add comment to burn damage reduction class * Added changes from Discord thread --------- Co-authored-by: Benjamin Odom --- src/data/move.ts | 22 +++++++++++++++++++++- src/field/pokemon.ts | 12 +++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 2a841a40150..652e832fdd6 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1353,6 +1353,25 @@ export class BypassSleepAttr extends MoveAttr { } } +/** + * Attribute used for moves that bypass the burn damage reduction of physical moves, currently only facade + * Called during damage calculation + * @param user N/A + * @param target N/A + * @param move Move with this attribute + * @param args Utils.BooleanHolder for burnDamageReductionCancelled + * @returns true if the function succeeds + */ +export class BypassBurnDamageReductionAttr extends MoveAttr { + + /** Prevents the move's damage from being reduced by burn */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + (args[0] as Utils.BooleanHolder).value = true; + + return true; + } +} + export class WeatherChangeAttr extends MoveEffectAttr { private weatherType: WeatherType; @@ -4904,7 +4923,8 @@ export function initMoves() { .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -2), new AttackMove(Moves.FACADE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 3) .attr(MovePowerMultiplierAttr, (user, target, move) => user.status - && (user.status.effect === StatusEffect.BURN || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.PARALYSIS) ? 2 : 1), + && (user.status.effect === StatusEffect.BURN || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.PARALYSIS) ? 2 : 1) + .attr(BypassBurnDamageReductionAttr), new AttackMove(Moves.FOCUS_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 150, 100, 20, -1, -3, 3) .punchingMove() .ignoresVirtual() diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 307f98f2f2d..245820484bd 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -4,7 +4,7 @@ import { Variant, VariantSet, variantColorCache } from '#app/data/variant'; 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, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr } from "../data/move"; +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, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr } from "../data/move"; 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'; @@ -1540,10 +1540,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!isTypeImmune) { damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier.value * screenMultiplier.value * ((this.scene.randBattleSeedInt(15) + 85) / 100) * criticalMultiplier.value); if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) { - const burnDamageReductionCancelled = new Utils.BooleanHolder(false); - applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled); - if (!burnDamageReductionCancelled.value) - damage.value = Math.floor(damage.value / 2); + if(!move.getAttrs(BypassBurnDamageReductionAttr).length) { + const burnDamageReductionCancelled = new Utils.BooleanHolder(false); + applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled); + if (!burnDamageReductionCancelled.value) + damage.value = Math.floor(damage.value / 2); + } } applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, battlerMove, damage); From 40993793cb7e3ad7e690c3e50d3e858abd1e2e97 Mon Sep 17 00:00:00 2001 From: Matthew Olker Date: Mon, 13 May 2024 14:23:34 -0400 Subject: [PATCH 06/27] Show default icon for missing starter icon --- src/ui/starter-select-ui-handler.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 148600b8d31..b9ed8195c0d 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -357,6 +357,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { icon.setScale(0.5); icon.setOrigin(0, 0); icon.setFrame(species.getIconId(defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant)); + this.checkIconId(icon, species, defaultProps.female, defaultProps.formIndex, defaultProps.shiny, defaultProps.variant); icon.setTint(0); this.starterSelectGenIconContainers[g].add(icon); this.iconAnimHandler.addOrUpdate(icon, PokemonIconAnimMode.NONE); @@ -792,6 +793,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor); this.starterIcons[this.starterCursors.length].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant)); this.starterIcons[this.starterCursors.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant)); + this.checkIconId(this.starterIcons[this.starterCursors.length], species, props.female, props.formIndex, props.shiny, props.variant); this.starterGens.push(this.getGenCursorWithScroll()); this.starterCursors.push(this.cursor); this.starterAttr.push(this.dexAttrCursor); @@ -1306,6 +1308,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr); const lastSpeciesIcon = (this.starterSelectGenIconContainers[this.lastSpecies.generation - 1].getAt(this.genSpecies[this.lastSpecies.generation - 1].indexOf(this.lastSpecies)) as Phaser.GameObjects.Sprite); lastSpeciesIcon.setTexture(this.lastSpecies.getIconAtlasKey(props.formIndex, props.shiny, props.variant), this.lastSpecies.getIconId(props.female, props.formIndex, props.shiny, props.variant)); + this.checkIconId(lastSpeciesIcon, this.lastSpecies, props.female, props.formIndex, props.shiny, props.variant); this.iconAnimHandler.addOrUpdate(lastSpeciesIcon, PokemonIconAnimMode.NONE); } @@ -1548,12 +1551,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { (this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite) .setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female, formIndex, shiny, variant)); - // Temporary fix to show pokemon's default icon if variant icon doesn't exist - if ((this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite).frame.name != species.getIconId(female, formIndex, shiny, variant)) { - console.log(`${species.name}'s variant icon does not exist. Replacing with default.`); - (this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite).setTexture(species.getIconAtlasKey(formIndex, false, variant)); - (this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite).setFrame(species.getIconId(female, formIndex, false, variant)); - } + this.checkIconId((this.starterSelectGenIconContainers[this.getGenCursorWithScroll()].getAt(this.cursor) as Phaser.GameObjects.Sprite), species, female, formIndex, shiny, variant); this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY); this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE); this.canCycleAbility = [ abilityAttr & AbilityAttr.ABILITY_1, (abilityAttr & AbilityAttr.ABILITY_2) && species.ability2, abilityAttr & AbilityAttr.ABILITY_HIDDEN ].filter(a => a).length > 1; @@ -1827,4 +1825,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (this.statsMode) this.toggleStatsMode(false); } + + checkIconId(icon: Phaser.GameObjects.Sprite, species: PokemonSpecies, female, formIndex, shiny, variant) { + if (icon.frame.name != species.getIconId(female, formIndex, shiny, variant)) { + console.log(`${species.name}'s variant icon does not exist. Replacing with default.`); + icon.setTexture(species.getIconAtlasKey(formIndex, false, variant)); + icon.setFrame(species.getIconId(female, formIndex, false, variant)); + } + } } \ No newline at end of file From 487b1d26d140528326ed35272154caa4144b4d66 Mon Sep 17 00:00:00 2001 From: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> Date: Mon, 13 May 2024 20:24:55 +0200 Subject: [PATCH 07/27] Added german localization to the new entries in starter-select-ui-handler.ts (#822) --- src/locales/de/starter-select-ui-handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/locales/de/starter-select-ui-handler.ts b/src/locales/de/starter-select-ui-handler.ts index 5ee3da9db0d..791a7c053d4 100644 --- a/src/locales/de/starter-select-ui-handler.ts +++ b/src/locales/de/starter-select-ui-handler.ts @@ -29,6 +29,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleVariant": "V: Seltenheit ändern", "enablePassive": "Passiv-Skill aktivieren", "disablePassive": "Passiv-Skill deaktivieren", - "locked": "Locked", - "disabled": "Disabled" + "locked": "Gesperrt", + "disabled": "Deaktiviert" } \ No newline at end of file From e2dfbc4aa5904391c0309efb642e27163c8d20de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ricardo=20Fleury=20Oliveira?= Date: Mon, 13 May 2024 15:55:15 -0300 Subject: [PATCH 08/27] Added new entries (#823) --- src/locales/pt_BR/starter-select-ui-handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/locales/pt_BR/starter-select-ui-handler.ts b/src/locales/pt_BR/starter-select-ui-handler.ts index 4877c169141..999b8bdfde2 100644 --- a/src/locales/pt_BR/starter-select-ui-handler.ts +++ b/src/locales/pt_BR/starter-select-ui-handler.ts @@ -29,6 +29,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "cycleVariant": 'V: Mudar Variante', "enablePassive": "Ativar Passiva", "disablePassive": "Desativar Passiva", - "locked": "Locked", - "disabled": "Disabled" + "locked": "Bloqueado", + "disabled": "Desativado", } \ No newline at end of file From 47c9eb547d0f630d18caf14f7ba12a197940619d Mon Sep 17 00:00:00 2001 From: Matthew Olker Date: Mon, 13 May 2024 15:29:50 -0400 Subject: [PATCH 09/27] fix Rare Shiny Groudon back sprite --- public/images/pokemon/variant/back/383_2.png | Bin 4283 -> 61670 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/pokemon/variant/back/383_2.png b/public/images/pokemon/variant/back/383_2.png index aea0b02b481158a179635caf70e3c2b0aa95e4ac..0d25afe7e54e6a79f049942bb9dee8113718f733 100644 GIT binary patch delta 59361 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 Date: Mon, 13 May 2024 13:53:23 -0600 Subject: [PATCH 10/27] Fix Zygarge Complete form changing back into 50% (#786) --- src/data/ability.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index fee574e4a5e..b2899a33ff2 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -3463,9 +3463,9 @@ export function initAbilities() { .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr), new Ability(Abilities.POWER_CONSTRUCT, 7) // TODO: 10% Power Construct Zygarde isn't accounted for yet. If changed, update Zygarde's getSpeciesFormIndex entry accordingly - .attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 4 : 2) - .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 4 : 2) - .attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 4 : 2) + .attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === 'complete' ? 4 : 2) + .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === 'complete' ? 4 : 2) + .attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === 'complete' ? 4 : 2) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) From 7e5c7fb4f7e3cbc172dd36c634d1e0a2d8e83946 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Mon, 13 May 2024 17:03:53 -0400 Subject: [PATCH 11/27] Don't allow trainer egg moves before level 60 and no rare egg moves at all --- src/field/pokemon.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 245820484bd..fd1613df1c7 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1225,24 +1225,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } } - if (this.level >= 25) { // No egg moves below level 25 + if (this.level >= 60) { // No egg moves below level 60 for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.species.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)')) movePool.push([moveId, Math.min(this.level * 0.5, 40)]); } - const moveId = speciesEggMoves[this.species.getRootSpeciesId()][3]; - if (this.level >= 60 && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)')) // No rare egg moves before level 60 - movePool.push([moveId, Math.min(this.level * 0.2, 20)]); if (this.fusionSpecies) { for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)')) movePool.push([moveId, Math.min(this.level * 0.5, 30)]); } - const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][3]; - if (this.level >= 60 && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(' (N)')) // No rare egg moves before level 60 - movePool.push([moveId, Math.min(this.level * 0.2, 20)]); } } } From b45cd2f7e79fbe2ea65b8148ebbefccdf28bbb3f Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Mon, 13 May 2024 18:17:57 -0400 Subject: [PATCH 12/27] Implement hybrid saving for optimization --- src/phases.ts | 2 +- src/system/game-data.ts | 104 ++++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 58 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 271e5350c82..6cc6af93ef9 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -775,7 +775,7 @@ export class EncounterPhase extends BattlePhase { this.scene.ui.setMode(Mode.MESSAGE).then(() => { if (!this.loaded) { - this.scene.gameData.saveAll(this.scene, true).then(success => { + this.scene.gameData.saveAll(this.scene, true, battle.waveIndex % 5 === 1).then(success => { this.scene.disableMenu = false; if (!success) return this.scene.reset(true); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 7f6e1475b4a..90722d1ce37 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -277,7 +277,7 @@ export class GameData { const maxIntAttrValue = Math.pow(2, 31); const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v); - if (!bypassLogin) { + if (!bypassLogin && !localStorage.getItem('data')) { Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true) .then(response => response.text()) .then(error => { @@ -293,12 +293,15 @@ export class GameData { console.error(error); return resolve(false); } + localStorage.removeItem('data'); resolve(true); }); } else { - localStorage.setItem('data_bak', localStorage.getItem('data')); + const encFunc = bypassLogin + ? (data: string) => btoa(data) + : (data: string) => AES.encrypt(data, saveKey); - localStorage.setItem('data', btoa(systemData)); + localStorage.setItem('data', encFunc(systemData)); this.scene.ui.savingIcon.hide(); @@ -309,7 +312,7 @@ export class GameData { public loadSystem(): Promise { return new Promise(resolve => { - if (bypassLogin && !localStorage.hasOwnProperty('data')) + if (bypassLogin && !localStorage.getItem('data')) return resolve(false); const handleSystemData = (systemDataStr: string) => { @@ -421,7 +424,7 @@ export class GameData { } } - if (!bypassLogin) { + if (!bypassLogin && !localStorage.getItem('data')) { Utils.apiFetch(`savedata/get?datatype=${GameDataType.SYSTEM}`, true) .then(response => response.text()) .then(response => { @@ -439,8 +442,12 @@ export class GameData { handleSystemData(response); }); - } else - handleSystemData(atob(localStorage.getItem('data'))); + } else { + const decFunc = bypassLogin + ? (data: string) => atob(data) + : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8); + handleSystemData(decFunc(localStorage.getItem('data'))); + } }); } @@ -557,40 +564,6 @@ export class GameData { } as SessionSaveData; } - saveSession(scene: BattleScene, skipVerification?: boolean): Promise { - return new Promise(resolve => { - Utils.executeIf(!skipVerification, updateUserInfo).then(success => { - if (success !== null && !success) - return resolve(false); - - const sessionData = this.getSessionSaveData(scene); - - if (!bypassLogin) { - Utils.apiPost(`savedata/update?datatype=${GameDataType.SESSION}&slot=${scene.sessionSlotId}&trainerId=${this.trainerId}&secretId=${this.secretId}`, JSON.stringify(sessionData), undefined, true) - .then(response => response.text()) - .then(error => { - if (error) { - if (error.startsWith('session out of date')) { - this.scene.clearPhaseQueue(); - this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); - } - console.error(error); - return resolve(false); - } - console.debug('Session data saved'); - resolve(true); - }); - } else { - localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, btoa(JSON.stringify(sessionData))); - - console.debug('Session data saved'); - - resolve(true); - } - }); - }); - } - getSession(slotId: integer): Promise { return new Promise(async (resolve, reject) => { if (slotId < 0) @@ -605,7 +578,7 @@ export class GameData { } }; - if (!bypassLogin) { + if (!bypassLogin && !localStorage.getItem(`sessionData${slotId ? slotId : ''}`)) { Utils.apiFetch(`savedata/get?datatype=${GameDataType.SESSION}&slot=${slotId}`, true) .then(response => response.text()) .then(async response => { @@ -618,9 +591,12 @@ export class GameData { }); } else { const sessionData = localStorage.getItem(`sessionData${slotId ? slotId : ''}`); - if (sessionData) - await handleSessionData(atob(sessionData)); - else + if (sessionData) { + const decFunc = bypassLogin + ? (data: string) => atob(data) + : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8); + await handleSessionData(decFunc(sessionData)); + } else return resolve(null); } }); @@ -731,7 +707,7 @@ export class GameData { deleteSession(slotId: integer): Promise { return new Promise(resolve => { if (bypassLogin) { - localStorage.removeItem('sessionData'); + localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}`); return resolve(true); } @@ -741,6 +717,7 @@ export class GameData { Utils.apiFetch(`savedata/delete?datatype=${GameDataType.SESSION}&slot=${slotId}`, true).then(response => { if (response.ok) { loggedInUser.lastSessionSlot = -1; + localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}`); resolve(true); } return response.text(); @@ -771,8 +748,10 @@ export class GameData { return resolve([false, false]); const sessionData = this.getSessionSaveData(scene); Utils.apiPost(`savedata/clear?slot=${slotId}&trainerId=${this.trainerId}&secretId=${this.secretId}`, JSON.stringify(sessionData), undefined, true).then(response => { - if (response.ok) + if (response.ok) { loggedInUser.lastSessionSlot = -1; + localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}`); + } return response.json(); }).then(jsonResponse => { if (!jsonResponse.error) @@ -825,13 +804,12 @@ export class GameData { }) as SessionSaveData; } - saveAll(scene: BattleScene, skipVerification?: boolean): Promise { + saveAll(scene: BattleScene, skipVerification: boolean = false, sync: boolean = false): Promise { return new Promise(resolve => { Utils.executeIf(!skipVerification, updateUserInfo).then(success => { if (success !== null && !success) return resolve(false); this.scene.ui.savingIcon.show(); - const data = this.getSystemSaveData(); const sessionData = this.getSessionSaveData(scene); const maxIntAttrValue = Math.pow(2, 31); @@ -843,7 +821,7 @@ export class GameData { sessionSlotId: scene.sessionSlotId }; - if (!bypassLogin) { + if (!bypassLogin && sync) { Utils.apiPost('savedata/updateall', JSON.stringify(request, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v), undefined, true) .then(response => response.text()) .then(error => { @@ -859,14 +837,18 @@ export class GameData { console.error(error); return resolve(false); } + localStorage.removeItem('data'); + localStorage.removeItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`); resolve(true); }); } else { - localStorage.setItem('data_bak', localStorage.getItem('data')); + const encFunc = bypassLogin + ? (data: string) => btoa(data) + : (data: string) => AES.encrypt(data, saveKey); - localStorage.setItem('data', btoa(JSON.stringify(systemData, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v))); + localStorage.setItem('data', encFunc(JSON.stringify(systemData, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v))); - localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, btoa(JSON.stringify(sessionData))); + localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, encFunc(JSON.stringify(sessionData))); console.debug('Session data saved'); @@ -910,8 +892,12 @@ export class GameData { }); } else { const data = localStorage.getItem(dataKey); - if (data) - handleData(atob(data)); + if (data) { + const decFunc = bypassLogin + ? (data: string) => atob(data) + : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8); + handleData(decFunc(data)); + } resolve(!!data); } }); @@ -979,7 +965,7 @@ export class GameData { return this.scene.ui.showText(`Your ${dataName} data could not be loaded. It may be corrupted.`, null, () => this.scene.ui.showText(null, 0), Utils.fixedInt(1500)); this.scene.ui.showText(`Your ${dataName} data will be overridden and the page will reload. Proceed?`, null, () => { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { - if (!bypassLogin && dataType < GameDataType.SETTINGS) { + if (!bypassLogin && dataType < GameDataType.SETTINGS && localStorage.getItem(dataKey)) { updateUserInfo().then(success => { if (!success) return displayError(`Could not contact the server. Your ${dataName} data could not be imported.`); @@ -990,11 +976,15 @@ export class GameData { console.error(error); return displayError(`An error occurred while updating ${dataName} data. Please contact the administrator.`); } + localStorage.removeItem(dataKey); window.location = window.location; }); }); } else { - localStorage.setItem(dataKey, btoa(dataStr)); + const encFunc = bypassLogin || dataType === GameDataType.SETTINGS + ? (data: string) => btoa(data) + : (data: string) => AES.encrypt(data, saveKey); + localStorage.setItem(dataKey, encFunc(dataStr)); window.location = window.location; } }, () => { From 5d0dbfff98c19284a6fc65f0f36666a0011b86a6 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Mon, 13 May 2024 18:37:48 -0400 Subject: [PATCH 13/27] Only show save icon on server sync --- src/system/game-data.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 90722d1ce37..d0e296cc4c0 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -809,7 +809,8 @@ export class GameData { Utils.executeIf(!skipVerification, updateUserInfo).then(success => { if (success !== null && !success) return resolve(false); - this.scene.ui.savingIcon.show(); + if (sync) + this.scene.ui.savingIcon.show(); const sessionData = this.getSessionSaveData(scene); const maxIntAttrValue = Math.pow(2, 31); @@ -825,7 +826,8 @@ export class GameData { Utils.apiPost('savedata/updateall', JSON.stringify(request, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v), undefined, true) .then(response => response.text()) .then(error => { - this.scene.ui.savingIcon.hide(); + if (sync) + this.scene.ui.savingIcon.hide(); if (error) { if (error.startsWith('client version out of date')) { this.scene.clearPhaseQueue(); From 3a3611dfc0d9ad72e7cb6df08d48b063f93ecc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ricardo=20Fleury=20Oliveira?= Date: Mon, 13 May 2024 19:59:09 -0300 Subject: [PATCH 14/27] Minor translation fixes (#829) --- src/locales/pt_BR/battle.ts | 2 +- src/locales/pt_BR/tutorial.ts | 54 ++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/locales/pt_BR/battle.ts b/src/locales/pt_BR/battle.ts index 6891e3b2e9a..ed579845cd7 100644 --- a/src/locales/pt_BR/battle.ts +++ b/src/locales/pt_BR/battle.ts @@ -9,7 +9,7 @@ export const battle: SimpleTranslationEntries = { "trainerComeBack": "{{trainerName}} retirou {{pokemonName}} da batalha!", "playerGo": "{{pokemonName}}, eu escolho você!", "trainerGo": "{{trainerName}} enviou {{pokemonName}}!", - "switchQuestion": "Quer trocar\n{{pokemonName}}?", + "switchQuestion": "Quer trocar\nde {{pokemonName}}?", "trainerDefeated": "Você derrotou\n{{trainerName}}!", "pokemonCaught": "{{pokemonName}} foi capturado!", "pokemon": "Pokémon", diff --git a/src/locales/pt_BR/tutorial.ts b/src/locales/pt_BR/tutorial.ts index d217cc2cde0..1f79616481f 100644 --- a/src/locales/pt_BR/tutorial.ts +++ b/src/locales/pt_BR/tutorial.ts @@ -1,43 +1,51 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const tutorial: SimpleTranslationEntries = { - "intro": `Bem-vindo ao PokéRogue! Este é um jogo de Pokémon feito por fãs focado em batalha com elementos roguelite. - $Este jogo não é monetizado e não reivindicamos propriedade de Pokémon nem dos ativos protegidos por direitos autorais usados. - $O jogo é um trabalho em andamento, mas totalmente jogável.\nPara relatórios de bugs, use a comunidade no Discord. - $Se o jogo rodar lentamente, certifique-se de que a 'Aceleração de hardware' esteja ativada nas configurações do seu navegador.`, + "intro": `Bem-vindo ao PokéRogue! Este é um jogo Pokémon feito por fãs focado em batalhas com elementos roguelite. + $Este jogo não é monetizado e não reivindicamos propriedade de Pokémon nem dos ativos protegidos + $por direitos autorais usados. + $O jogo é um trabalho em andamento, mas é totalmente jogável. + $Para relatórios de bugs, use a comunidade no Discord. + $Se o jogo estiver rodando lentamente, certifique-se de que a 'Aceleração de hardware' esteja ativada + $nas configurações do seu navegador.`, "accessMenu": `Para acessar o menu, aperte M ou Esc. $O menu contém configurações e diversas funções.`, "menu": `A partir deste menu, você pode acessar as configurações. - $Nas configurações, você pode alterar a velocidade do jogo, o estilo da janela e outras opções. - $Existem também vários outros recursos aqui, então não deixe de conferir todos eles!`, + $Nas configurações, você pode alterar a velocidade do jogo, + $o estilo da janela, entre outras opções. + $Existem também vários outros recursos disponíveis aqui. + $Não deixe de conferir todos eles!`, - "starterSelect": `Nessa tela, você pode selecionar seus iniciais.\nEsses são os Pokémon iniciais da sua equipe. - $Cada inicial tem seu próprio custo. Sua equipe pode ter até \n6 membros contando que o preço não ultrapasse 10. - $Você pode também selecionar o gênero, habilidade, e formas dependendo \ndas variantes que você capturou ou chocou. - $Os IVs da espécie são os melhores de todos que você \njá capturou ou chocou, então tente conseguir vários Pokémon da mesma espécie!`, + "starterSelect": `Aqui você pode escolher seus iniciais.\nEsses serão os primeiro Pokémon da sua equipe. + $Cada inicial tem seu custo. Sua equipe pode ter até 6\nmembros, desde que a soma dos custos não ultrapasse 10. + $Você pode escolher o gênero, a habilidade\ne até a forma do seu inicial. + $Essas opções dependem das variantes dessa\nespécie que você já capturou ou chocou. + $Os IVs de cada inicial são os melhores de todos os Pokémon\ndaquela espécie que você já capturou ou chocou. + $Sempre capture vários Pokémon de várias espécies!`, - "pokerus": `Todo dia, 3 Pokémon iniciais ficam com uma borda roxa. + "pokerus": `Todo dia, 3 Pokémon iniciais ficam com uma borda roxa. $Caso veja um inicial que você possui com uma dessa, tente\nadicioná-lo a sua equipe. Lembre-se de olhar seu sumário!`, - "statChange": `As mudanças de estatísticas se mantém depois do combate\ndesde que o Pokémon não seja trocado. + "statChange": `As mudanças de atributos se mantém após a batalha desde que o Pokémon não seja trocado. $Seus Pokémon voltam a suas Poké Bolas antes de batalhas contra treinadores e de entrar em um novo bioma. - $Também é possível ver as mudanças de estatísticas dos Pokémon em campo mantendo pressionado C ou Shift.`, + $Para ver as mudanças de atributos dos Pokémon em campo, mantena C ou Shift pressionado durante a batalha.`, - "selectItem": `Após cada batalha você pode escolher entre 3 itens aleatórios.\nVocê pode escolher apenas um. - $Esses variam entre consumíveis, itens de segurar, e itens passivos permanentes. - $A maioria dos efeitos de itens não consumíveis serão acumulados de várias maneiras. - $Alguns itens só aparecerão se puderem ser usados, por exemplo, itens de evolução. - $Você também pode transferir itens de segurar entre os Pokémon utilizando a opção de transferir. + "selectItem": `Após cada batalha, você pode escolher entre 3 itens aleatórios. + $Você pode escolher apenas um deles. + $Esses itens variam entre consumíveis, itens de segurar e itens passivos permanentes. + $A maioria dos efeitos de itens não consumíveis podem ser acumulados. + $Alguns itens só aparecerão se puderem ser usados, como os itens de evolução. + $Você também pode transferir itens de segurar entre os Pokémon utilizando a opção "Transfer". $A opção de transferir irá aparecer no canto inferior direito assim que você obter um item de segurar. - $Você pode comprar itens consumíveis com dinheiro, e uma maior variedade ficará disponível conforme você for mais longe. - $Certifique-se de comprá-los antes de escolher seu item aleatório. Ao escolher, a próxima batalha começará.`, + $Você pode comprar itens consumíveis com dinheiro, e sua variedade aumentará conforme você for mais longe. + $Certifique-se de comprá-los antes de escolher seu item aleatório. Ao escolhê-lo, a próxima batalha começará.`, - "eggGacha": `Nesta tela você pode trocar seus vouchers\npor ovos de Pokémon. - $Ovos ficam mais próximos de chocar depois de cada batalha.\nOvos raros demoram mais para chocar. + "eggGacha": `Aqui você pode trocar seus vouchers\npor ovos de Pokémon. + $Ovos ficam mais próximos de chocar após cada batalha.\nOvos mais raros demoram mais para chocar. $Pokémon chocados não serão adicionados a sua equipe,\nmas sim aos seus iniciais. $Pokémon chocados geralmente possuem IVs melhores\nque Pokémon selvagens. $Alguns Pokémon só podem ser obtidos através de seus ovos. - $Há 3 máquinas, cada uma com um bônus diferente,\nentão escolha a que mais lhe convém!`, + $Temos 3 máquinas, cada uma com seu bônus específico,\nentão escolha a que mais lhe convém!`, } as const; \ No newline at end of file From 74ee3329f8ea6975b474f63b45255dac63d7a888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ricardo=20Fleury=20Oliveira?= Date: Mon, 13 May 2024 20:02:44 -0300 Subject: [PATCH 15/27] Added "Uncaught" localization in Starter Selection UI (#831) --- src/locales/de/starter-select-ui-handler.ts | 3 +- src/locales/en/starter-select-ui-handler.ts | 3 +- src/locales/es/starter-select-ui-handler.ts | 3 +- src/locales/fr/starter-select-ui-handler.ts | 3 +- src/locales/it/starter-select-ui-handler.ts | 3 +- .../pt_BR/starter-select-ui-handler.ts | 1 + .../zh_CN/starter-select-ui-handler.ts | 3 +- src/ui/starter-select-ui-handler.ts | 58 +++++++++---------- 8 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/locales/de/starter-select-ui-handler.ts b/src/locales/de/starter-select-ui-handler.ts index 791a7c053d4..2e733c1a0ed 100644 --- a/src/locales/de/starter-select-ui-handler.ts +++ b/src/locales/de/starter-select-ui-handler.ts @@ -30,5 +30,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "enablePassive": "Passiv-Skill aktivieren", "disablePassive": "Passiv-Skill deaktivieren", "locked": "Gesperrt", - "disabled": "Deaktiviert" + "disabled": "Deaktiviert", + "uncaught": "Uncaught" } \ No newline at end of file diff --git a/src/locales/en/starter-select-ui-handler.ts b/src/locales/en/starter-select-ui-handler.ts index dd3904e121b..2acceab69ff 100644 --- a/src/locales/en/starter-select-ui-handler.ts +++ b/src/locales/en/starter-select-ui-handler.ts @@ -30,5 +30,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "enablePassive": "Enable Passive", "disablePassive": "Disable Passive", "locked": "Locked", - "disabled": "Disabled" + "disabled": "Disabled", + "uncaught": "Uncaught" } \ No newline at end of file diff --git a/src/locales/es/starter-select-ui-handler.ts b/src/locales/es/starter-select-ui-handler.ts index e8cd9bce0de..9b037209819 100644 --- a/src/locales/es/starter-select-ui-handler.ts +++ b/src/locales/es/starter-select-ui-handler.ts @@ -30,5 +30,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "enablePassive": "Activar Pasiva", "disablePassive": "Desactivar Pasiva", "locked": "Locked", - "disabled": "Disabled" + "disabled": "Disabled", + "uncaught": "Uncaught" } \ No newline at end of file diff --git a/src/locales/fr/starter-select-ui-handler.ts b/src/locales/fr/starter-select-ui-handler.ts index 9f4309e40f4..d26fa3314b6 100644 --- a/src/locales/fr/starter-select-ui-handler.ts +++ b/src/locales/fr/starter-select-ui-handler.ts @@ -30,5 +30,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "enablePassive": "Activer Passif", "disablePassive": "Désactiver Passif", "locked": "Verrouillé", - "disabled": "Désactivé" + "disabled": "Désactivé", + "uncaught": "Uncaught" } diff --git a/src/locales/it/starter-select-ui-handler.ts b/src/locales/it/starter-select-ui-handler.ts index e8c58ad138d..79c2e26c642 100644 --- a/src/locales/it/starter-select-ui-handler.ts +++ b/src/locales/it/starter-select-ui-handler.ts @@ -30,5 +30,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "enablePassive": "Attiva Passiva", "disablePassive": "Disattiva Passiva", "locked": "Locked", - "disabled": "Disabled" + "disabled": "Disabled", + "uncaught": "Uncaught" } \ No newline at end of file diff --git a/src/locales/pt_BR/starter-select-ui-handler.ts b/src/locales/pt_BR/starter-select-ui-handler.ts index 999b8bdfde2..ba180c2cfb2 100644 --- a/src/locales/pt_BR/starter-select-ui-handler.ts +++ b/src/locales/pt_BR/starter-select-ui-handler.ts @@ -31,4 +31,5 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "disablePassive": "Desativar Passiva", "locked": "Bloqueado", "disabled": "Desativado", + "uncaught": "Não capturado" } \ No newline at end of file diff --git a/src/locales/zh_CN/starter-select-ui-handler.ts b/src/locales/zh_CN/starter-select-ui-handler.ts index c2d0a82d837..ace02c1c227 100644 --- a/src/locales/zh_CN/starter-select-ui-handler.ts +++ b/src/locales/zh_CN/starter-select-ui-handler.ts @@ -30,5 +30,6 @@ export const starterSelectUiHandler: SimpleTranslationEntries = { "enablePassive": "启用被动", "disablePassive": "禁用被动", "locked": "Locked", - "disabled": "Disabled" + "disabled": "Disabled", + "uncaught": "Uncaught" } \ No newline at end of file diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index b9ed8195c0d..8443ed5741e 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -1,34 +1,34 @@ -import BattleScene, { starterColors } from "../battle-scene"; -import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, speciesStarters, starterPassiveAbilities, getStarterValueFriendshipCap } from "../data/pokemon-species"; -import { Species } from "../data/enums/species"; -import { TextStyle, addBBCodeTextObject, addTextObject } from "./text"; -import { Mode } from "./ui"; -import MessageUiHandler from "./message-ui-handler"; -import { Gender, getGenderColor, getGenderSymbol } from "../data/gender"; -import { allAbilities } from "../data/ability"; -import { GameModes, gameModes } from "../game-mode"; -import { GrowthRate, getGrowthRateColor } from "../data/exp"; -import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, Passive as PassiveAttr, StarterFormMoveData, StarterMoveset } from "../system/game-data"; -import * as Utils from "../utils"; -import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim-handler"; -import { StatsContainer } from "./stats-container"; -import { addWindow } from "./ui-theme"; -import { Nature, getNatureName } from "../data/nature"; -import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; -import { pokemonFormChanges } from "../data/pokemon-forms"; -import { Tutorial, handleTutorial } from "../tutorial"; -import { LevelMoves, pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "../data/pokemon-level-moves"; -import { allMoves } from "../data/move"; -import { Type } from "../data/type"; -import { Moves } from "../data/enums/moves"; -import { speciesEggMoves } from "../data/egg-moves"; -import { TitlePhase } from "../phases"; -import { argbFromRgba } from "@material/material-color-utilities"; -import { OptionSelectItem } from "./abstact-option-select-ui-handler"; import { pokemonPrevolutions } from "#app/data/pokemon-evolutions"; import { Variant, getVariantTint } from "#app/data/variant"; +import { argbFromRgba } from "@material/material-color-utilities"; import i18next from "i18next"; -import {Button} from "../enums/buttons"; +import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; +import BattleScene, { starterColors } from "../battle-scene"; +import { allAbilities } from "../data/ability"; +import { speciesEggMoves } from "../data/egg-moves"; +import { Moves } from "../data/enums/moves"; +import { Species } from "../data/enums/species"; +import { GrowthRate, getGrowthRateColor } from "../data/exp"; +import { Gender, getGenderColor, getGenderSymbol } from "../data/gender"; +import { allMoves } from "../data/move"; +import { Nature, getNatureName } from "../data/nature"; +import { pokemonFormChanges } from "../data/pokemon-forms"; +import { LevelMoves, pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "../data/pokemon-level-moves"; +import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species"; +import { Type } from "../data/type"; +import { Button } from "../enums/buttons"; +import { GameModes, gameModes } from "../game-mode"; +import { TitlePhase } from "../phases"; +import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, Passive as PassiveAttr, StarterFormMoveData, StarterMoveset } from "../system/game-data"; +import { Tutorial, handleTutorial } from "../tutorial"; +import * as Utils from "../utils"; +import { OptionSelectItem } from "./abstact-option-select-ui-handler"; +import MessageUiHandler from "./message-ui-handler"; +import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim-handler"; +import { StatsContainer } from "./stats-container"; +import { TextStyle, addBBCodeTextObject, addTextObject } from "./text"; +import { Mode } from "./ui"; +import { addWindow } from "./ui-theme"; export type StarterSelectCallback = (starters: Starter[]) => void; @@ -241,7 +241,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonGenderText.setOrigin(0, 0); this.starterSelectContainer.add(this.pokemonGenderText); - this.pokemonUncaughtText = addTextObject(this.scene, 6, 127, 'Uncaught', TextStyle.SUMMARY_ALT, { fontSize: '56px' }); + this.pokemonUncaughtText = addTextObject(this.scene, 6, 127, i18next.t("starterSelectUiHandler:uncaught"), TextStyle.SUMMARY_ALT, { fontSize: '56px' }); this.pokemonUncaughtText.setOrigin(0, 0); this.starterSelectContainer.add(this.pokemonUncaughtText); From 1c56efc860d5531d754c07f8785aa9cf8d0603af Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Mon, 13 May 2024 18:12:28 -0500 Subject: [PATCH 16/27] Added Ability Triggers Localization (#811) Adds the base files needed to start translating Ability trigger messages. Provides one as an example. --- src/data/ability.ts | 4 ++-- src/locales/de/ability-trigger.ts | 5 +++++ src/locales/de/config.ts | 2 ++ src/locales/en/ability-trigger.ts | 5 +++++ src/locales/en/config.ts | 4 +++- src/locales/es/ability-trigger.ts | 5 +++++ src/locales/es/config.ts | 2 ++ src/locales/fr/ability-trigger.ts | 5 +++++ src/locales/fr/config.ts | 2 ++ src/locales/it/ability-trigger.ts | 5 +++++ src/locales/it/config.ts | 2 ++ src/locales/zh_CN/ability-trigger.ts | 5 +++++ src/locales/zh_CN/config.ts | 2 ++ src/plugins/i18n.ts | 3 ++- 14 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 src/locales/de/ability-trigger.ts create mode 100644 src/locales/en/ability-trigger.ts create mode 100644 src/locales/es/ability-trigger.ts create mode 100644 src/locales/fr/ability-trigger.ts create mode 100644 src/locales/it/ability-trigger.ts create mode 100644 src/locales/zh_CN/ability-trigger.ts diff --git a/src/data/ability.ts b/src/data/ability.ts index b2899a33ff2..5ef07c39f7b 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -3,7 +3,7 @@ import { Type } from "./type"; import * as Utils from "../utils"; import { BattleStat, getBattleStatName } from "./battle-stat"; import { PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases"; -import { getPokemonMessage } from "../messages"; +import { getPokemonMessage, getPokemonPrefix } from "../messages"; import { Weather, WeatherType } from "./weather"; import { BattlerTag } from "./battler-tags"; import { BattlerTagType } from "./enums/battler-tag-type"; @@ -144,7 +144,7 @@ export class BlockRecoilDamageAttr extends AbAttr { } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { - return getPokemonMessage(pokemon, `'s ${abilityName}\nprotected it from recoil!`); + return i18next.t('abilityTriggers:blockRecoilDamage', {pokemonName: `${getPokemonPrefix(pokemon)}${pokemon.name}`, abilityName: abilityName}); } } diff --git a/src/locales/de/ability-trigger.ts b/src/locales/de/ability-trigger.ts new file mode 100644 index 00000000000..88900741218 --- /dev/null +++ b/src/locales/de/ability-trigger.ts @@ -0,0 +1,5 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const abilityTriggers: SimpleTranslationEntries = { + 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, +} as const; \ No newline at end of file diff --git a/src/locales/de/config.ts b/src/locales/de/config.ts index 2cc7a52c8f1..a9f4cd68297 100644 --- a/src/locales/de/config.ts +++ b/src/locales/de/config.ts @@ -1,4 +1,5 @@ import { ability } from "./ability"; +import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; import { fightUiHandler } from "./fight-ui-handler"; @@ -16,6 +17,7 @@ import { tutorial } from "./tutorial"; export const deConfig = { ability: ability, + abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, fightUiHandler: fightUiHandler, diff --git a/src/locales/en/ability-trigger.ts b/src/locales/en/ability-trigger.ts new file mode 100644 index 00000000000..88900741218 --- /dev/null +++ b/src/locales/en/ability-trigger.ts @@ -0,0 +1,5 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const abilityTriggers: SimpleTranslationEntries = { + 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, +} as const; \ No newline at end of file diff --git a/src/locales/en/config.ts b/src/locales/en/config.ts index 029791a701c..f5e8a68b09c 100644 --- a/src/locales/en/config.ts +++ b/src/locales/en/config.ts @@ -1,4 +1,5 @@ import { ability } from "./ability"; +import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; import { fightUiHandler } from "./fight-ui-handler"; @@ -14,8 +15,9 @@ import { starterSelectUiHandler } from "./starter-select-ui-handler"; import { tutorial } from "./tutorial"; -export const enConfig = { +export const enConfig = { ability: ability, + abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, fightUiHandler: fightUiHandler, diff --git a/src/locales/es/ability-trigger.ts b/src/locales/es/ability-trigger.ts new file mode 100644 index 00000000000..88900741218 --- /dev/null +++ b/src/locales/es/ability-trigger.ts @@ -0,0 +1,5 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const abilityTriggers: SimpleTranslationEntries = { + 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, +} as const; \ No newline at end of file diff --git a/src/locales/es/config.ts b/src/locales/es/config.ts index 564b8dd320d..c56a8d384c2 100644 --- a/src/locales/es/config.ts +++ b/src/locales/es/config.ts @@ -1,4 +1,5 @@ import { ability } from "./ability"; +import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; import { fightUiHandler } from "./fight-ui-handler"; @@ -16,6 +17,7 @@ import { tutorial } from "./tutorial"; export const esConfig = { ability: ability, + abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, fightUiHandler: fightUiHandler, diff --git a/src/locales/fr/ability-trigger.ts b/src/locales/fr/ability-trigger.ts new file mode 100644 index 00000000000..88900741218 --- /dev/null +++ b/src/locales/fr/ability-trigger.ts @@ -0,0 +1,5 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const abilityTriggers: SimpleTranslationEntries = { + 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, +} as const; \ No newline at end of file diff --git a/src/locales/fr/config.ts b/src/locales/fr/config.ts index 90f9fb83c53..89669aceb73 100644 --- a/src/locales/fr/config.ts +++ b/src/locales/fr/config.ts @@ -1,4 +1,5 @@ import { ability } from "./ability"; +import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; import { fightUiHandler } from "./fight-ui-handler"; @@ -16,6 +17,7 @@ import { tutorial } from "./tutorial"; export const frConfig = { ability: ability, + abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, fightUiHandler: fightUiHandler, diff --git a/src/locales/it/ability-trigger.ts b/src/locales/it/ability-trigger.ts new file mode 100644 index 00000000000..88900741218 --- /dev/null +++ b/src/locales/it/ability-trigger.ts @@ -0,0 +1,5 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const abilityTriggers: SimpleTranslationEntries = { + 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, +} as const; \ No newline at end of file diff --git a/src/locales/it/config.ts b/src/locales/it/config.ts index bbfd452dc39..6ba9aa3affa 100644 --- a/src/locales/it/config.ts +++ b/src/locales/it/config.ts @@ -1,4 +1,5 @@ import { ability } from "./ability"; +import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; import { fightUiHandler } from "./fight-ui-handler"; @@ -16,6 +17,7 @@ import { tutorial } from "./tutorial"; export const itConfig = { ability: ability, + abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, fightUiHandler: fightUiHandler, diff --git a/src/locales/zh_CN/ability-trigger.ts b/src/locales/zh_CN/ability-trigger.ts new file mode 100644 index 00000000000..88900741218 --- /dev/null +++ b/src/locales/zh_CN/ability-trigger.ts @@ -0,0 +1,5 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const abilityTriggers: SimpleTranslationEntries = { + 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, +} as const; \ No newline at end of file diff --git a/src/locales/zh_CN/config.ts b/src/locales/zh_CN/config.ts index a8f5f878ba0..496fd983c06 100644 --- a/src/locales/zh_CN/config.ts +++ b/src/locales/zh_CN/config.ts @@ -1,4 +1,5 @@ import { ability } from "./ability"; +import { abilityTriggers } from "./ability-trigger"; import { battle } from "./battle"; import { commandUiHandler } from "./command-ui-handler"; import { fightUiHandler } from "./fight-ui-handler"; @@ -15,6 +16,7 @@ import { nature } from "./nature"; export const zhCnConfig = { ability: ability, + abilityTriggers: abilityTriggers, battle: battle, commandUiHandler: commandUiHandler, fightUiHandler: fightUiHandler, diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 676e691ee29..82a5a51ba12 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -98,7 +98,8 @@ declare module 'i18next' { menu: SimpleTranslationEntries; menuUiHandler: SimpleTranslationEntries; move: MoveTranslationEntries; - battle: SimpleTranslationEntries, + battle: SimpleTranslationEntries; + abilityTriggers: SimpleTranslationEntries; ability: AbilityTranslationEntries; pokeball: SimpleTranslationEntries; pokemon: SimpleTranslationEntries; From 19d244ee949ef071847dce2806b2a1ac9e367798 Mon Sep 17 00:00:00 2001 From: JackGilham <46994951+JackGilham@users.noreply.github.com> Date: Tue, 14 May 2024 00:38:27 +0100 Subject: [PATCH 17/27] Update modifier-type.ts (#636) Issue#613. Have added additional EvolutionItemModifierType condition that prevents none base form pokes from taking Evo Items. --- src/modifier/modifier-type.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 2457a705bce..6b336523014 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -554,10 +554,10 @@ export class EvolutionItemModifierType extends PokemonModifierType implements Ge super(Utils.toReadableString(EvolutionItem[evolutionItem]), `Causes certain Pokémon to evolve`, (_type, args) => new Modifiers.EvolutionItemModifier(this, (args[0] as PlayerPokemon).id), (pokemon: PlayerPokemon) => { if (pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId) && pokemonEvolutions[pokemon.species.speciesId].filter(e => e.item === this.evolutionItem - && (!e.condition || e.condition.predicate(pokemon))).length) + && (!e.condition || e.condition.predicate(pokemon))).length && (pokemon.formIndex == 0)) return null; else if (pokemon.isFusion() && pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) && pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(e => e.item === this.evolutionItem - && (!e.condition || e.condition.predicate(pokemon))).length) + && (!e.condition || e.condition.predicate(pokemon))).length && (pokemon.fusionFormIndex == 0)) return null; return PartyUiHandler.NoEffectMessage; From 1d29ca797462ceeff3dbdbc9d005ec9c9ead113b Mon Sep 17 00:00:00 2001 From: LaukkaE <73663099+LaukkaE@users.noreply.github.com> Date: Tue, 14 May 2024 02:48:22 +0300 Subject: [PATCH 18/27] Fix Comeuppance (#781) --- 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 652e832fdd6..2b61d30b82c 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -6841,7 +6841,7 @@ export function initMoves() { const turnMove = user.getLastXMoves(1); return !turnMove.length || turnMove[0].move !== move.id || turnMove[0].result !== MoveResult.SUCCESS; }), // TODO Add Instruct/Encore interaction - new AttackMove(Moves.COMEUPPANCE, Type.DARK, MoveCategory.PHYSICAL, 1, 100, 10, -1, 0, 9) + 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), new AttackMove(Moves.AQUA_CUTTER, Type.WATER, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 9) From af86bdeb068388c2aa8d835c8e1413a335d99563 Mon Sep 17 00:00:00 2001 From: LaukkaE <73663099+LaukkaE@users.noreply.github.com> Date: Tue, 14 May 2024 02:48:47 +0300 Subject: [PATCH 19/27] Prevent applying item boosts when power is <1 (#795) * Prevent applying item boosts when power is <1 * add comments --- src/modifier/modifier.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index ba009cb7a8d..8a5fba17d1c 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -635,6 +635,9 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier { } } + /** + * Applies Specific Type item boosts (e.g., Magnet) + */ export class AttackTypeBoosterModifier extends PokemonHeldItemModifier { private moveType: Type; private boostMultiplier: number; @@ -667,8 +670,15 @@ export class AttackTypeBoosterModifier extends PokemonHeldItemModifier { return super.shouldApply(args) && args.length === 3 && typeof args[1] === 'number' && args[2] instanceof Utils.NumberHolder; } + /** + * @param {Array} args Array + * - Index 0: {Pokemon} Pokemon + * - Index 1: {number} Move type + * - Index 2: {Utils.NumberHolder} Move power + * @returns {boolean} Returns true if boosts have been applied to the move. + */ apply(args: any[]): boolean { - if (args[1] === this.moveType) { + if (args[1] === this.moveType && (args[2] as Utils.NumberHolder).value >= 1) { (args[2] as Utils.NumberHolder).value = Math.floor((args[2] as Utils.NumberHolder).value * (1 + (this.getStackCount() * this.boostMultiplier))); return true; } From 9d90cc3e1060c70228da61d07488e819f3031815 Mon Sep 17 00:00:00 2001 From: YounesM Date: Tue, 14 May 2024 01:52:36 +0200 Subject: [PATCH 20/27] corrected uturn flip turn crash (#596) --- src/field/damage-number-handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field/damage-number-handler.ts b/src/field/damage-number-handler.ts index f4a3d570e19..262ff8863d0 100644 --- a/src/field/damage-number-handler.ts +++ b/src/field/damage-number-handler.ts @@ -13,7 +13,7 @@ export default class DamageNumberHandler { add(target: Pokemon, amount: integer, result: DamageResult | HitResult.HEAL = HitResult.EFFECTIVE, critical: boolean = false): void { const scene = target.scene; - if (!scene.damageNumbersMode) + if (!scene?.damageNumbersMode) return; const battlerIndex = target.getBattlerIndex(); From ab92bc61ba2babee9ab917f79177aea092b669a2 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Mon, 13 May 2024 20:56:19 -0400 Subject: [PATCH 21/27] Revert "Only show save icon on server sync" This reverts commit 5d0dbfff98c19284a6fc65f0f36666a0011b86a6. --- src/system/game-data.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/system/game-data.ts b/src/system/game-data.ts index d0e296cc4c0..90722d1ce37 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -809,8 +809,7 @@ export class GameData { Utils.executeIf(!skipVerification, updateUserInfo).then(success => { if (success !== null && !success) return resolve(false); - if (sync) - this.scene.ui.savingIcon.show(); + this.scene.ui.savingIcon.show(); const sessionData = this.getSessionSaveData(scene); const maxIntAttrValue = Math.pow(2, 31); @@ -826,8 +825,7 @@ export class GameData { Utils.apiPost('savedata/updateall', JSON.stringify(request, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v), undefined, true) .then(response => response.text()) .then(error => { - if (sync) - this.scene.ui.savingIcon.hide(); + this.scene.ui.savingIcon.hide(); if (error) { if (error.startsWith('client version out of date')) { this.scene.clearPhaseQueue(); From 794363348199fd0df31dc0ba394b6c88a4da561c Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Mon, 13 May 2024 20:56:28 -0400 Subject: [PATCH 22/27] Revert "Implement hybrid saving for optimization" This reverts commit b45cd2f7e79fbe2ea65b8148ebbefccdf28bbb3f. --- src/phases.ts | 2 +- src/system/game-data.ts | 104 ++++++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 6cc6af93ef9..271e5350c82 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -775,7 +775,7 @@ export class EncounterPhase extends BattlePhase { this.scene.ui.setMode(Mode.MESSAGE).then(() => { if (!this.loaded) { - this.scene.gameData.saveAll(this.scene, true, battle.waveIndex % 5 === 1).then(success => { + this.scene.gameData.saveAll(this.scene, true).then(success => { this.scene.disableMenu = false; if (!success) return this.scene.reset(true); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 90722d1ce37..7f6e1475b4a 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -277,7 +277,7 @@ export class GameData { const maxIntAttrValue = Math.pow(2, 31); const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v); - if (!bypassLogin && !localStorage.getItem('data')) { + if (!bypassLogin) { Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true) .then(response => response.text()) .then(error => { @@ -293,15 +293,12 @@ export class GameData { console.error(error); return resolve(false); } - localStorage.removeItem('data'); resolve(true); }); } else { - const encFunc = bypassLogin - ? (data: string) => btoa(data) - : (data: string) => AES.encrypt(data, saveKey); + localStorage.setItem('data_bak', localStorage.getItem('data')); - localStorage.setItem('data', encFunc(systemData)); + localStorage.setItem('data', btoa(systemData)); this.scene.ui.savingIcon.hide(); @@ -312,7 +309,7 @@ export class GameData { public loadSystem(): Promise { return new Promise(resolve => { - if (bypassLogin && !localStorage.getItem('data')) + if (bypassLogin && !localStorage.hasOwnProperty('data')) return resolve(false); const handleSystemData = (systemDataStr: string) => { @@ -424,7 +421,7 @@ export class GameData { } } - if (!bypassLogin && !localStorage.getItem('data')) { + if (!bypassLogin) { Utils.apiFetch(`savedata/get?datatype=${GameDataType.SYSTEM}`, true) .then(response => response.text()) .then(response => { @@ -442,12 +439,8 @@ export class GameData { handleSystemData(response); }); - } else { - const decFunc = bypassLogin - ? (data: string) => atob(data) - : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8); - handleSystemData(decFunc(localStorage.getItem('data'))); - } + } else + handleSystemData(atob(localStorage.getItem('data'))); }); } @@ -564,6 +557,40 @@ export class GameData { } as SessionSaveData; } + saveSession(scene: BattleScene, skipVerification?: boolean): Promise { + return new Promise(resolve => { + Utils.executeIf(!skipVerification, updateUserInfo).then(success => { + if (success !== null && !success) + return resolve(false); + + const sessionData = this.getSessionSaveData(scene); + + if (!bypassLogin) { + Utils.apiPost(`savedata/update?datatype=${GameDataType.SESSION}&slot=${scene.sessionSlotId}&trainerId=${this.trainerId}&secretId=${this.secretId}`, JSON.stringify(sessionData), undefined, true) + .then(response => response.text()) + .then(error => { + if (error) { + if (error.startsWith('session out of date')) { + this.scene.clearPhaseQueue(); + this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); + } + console.error(error); + return resolve(false); + } + console.debug('Session data saved'); + resolve(true); + }); + } else { + localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, btoa(JSON.stringify(sessionData))); + + console.debug('Session data saved'); + + resolve(true); + } + }); + }); + } + getSession(slotId: integer): Promise { return new Promise(async (resolve, reject) => { if (slotId < 0) @@ -578,7 +605,7 @@ export class GameData { } }; - if (!bypassLogin && !localStorage.getItem(`sessionData${slotId ? slotId : ''}`)) { + if (!bypassLogin) { Utils.apiFetch(`savedata/get?datatype=${GameDataType.SESSION}&slot=${slotId}`, true) .then(response => response.text()) .then(async response => { @@ -591,12 +618,9 @@ export class GameData { }); } else { const sessionData = localStorage.getItem(`sessionData${slotId ? slotId : ''}`); - if (sessionData) { - const decFunc = bypassLogin - ? (data: string) => atob(data) - : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8); - await handleSessionData(decFunc(sessionData)); - } else + if (sessionData) + await handleSessionData(atob(sessionData)); + else return resolve(null); } }); @@ -707,7 +731,7 @@ export class GameData { deleteSession(slotId: integer): Promise { return new Promise(resolve => { if (bypassLogin) { - localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}`); + localStorage.removeItem('sessionData'); return resolve(true); } @@ -717,7 +741,6 @@ export class GameData { Utils.apiFetch(`savedata/delete?datatype=${GameDataType.SESSION}&slot=${slotId}`, true).then(response => { if (response.ok) { loggedInUser.lastSessionSlot = -1; - localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}`); resolve(true); } return response.text(); @@ -748,10 +771,8 @@ export class GameData { return resolve([false, false]); const sessionData = this.getSessionSaveData(scene); Utils.apiPost(`savedata/clear?slot=${slotId}&trainerId=${this.trainerId}&secretId=${this.secretId}`, JSON.stringify(sessionData), undefined, true).then(response => { - if (response.ok) { + if (response.ok) loggedInUser.lastSessionSlot = -1; - localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ''}`); - } return response.json(); }).then(jsonResponse => { if (!jsonResponse.error) @@ -804,12 +825,13 @@ export class GameData { }) as SessionSaveData; } - saveAll(scene: BattleScene, skipVerification: boolean = false, sync: boolean = false): Promise { + saveAll(scene: BattleScene, skipVerification?: boolean): Promise { return new Promise(resolve => { Utils.executeIf(!skipVerification, updateUserInfo).then(success => { if (success !== null && !success) return resolve(false); this.scene.ui.savingIcon.show(); + const data = this.getSystemSaveData(); const sessionData = this.getSessionSaveData(scene); const maxIntAttrValue = Math.pow(2, 31); @@ -821,7 +843,7 @@ export class GameData { sessionSlotId: scene.sessionSlotId }; - if (!bypassLogin && sync) { + if (!bypassLogin) { Utils.apiPost('savedata/updateall', JSON.stringify(request, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v), undefined, true) .then(response => response.text()) .then(error => { @@ -837,18 +859,14 @@ export class GameData { console.error(error); return resolve(false); } - localStorage.removeItem('data'); - localStorage.removeItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`); resolve(true); }); } else { - const encFunc = bypassLogin - ? (data: string) => btoa(data) - : (data: string) => AES.encrypt(data, saveKey); + localStorage.setItem('data_bak', localStorage.getItem('data')); - localStorage.setItem('data', encFunc(JSON.stringify(systemData, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v))); + localStorage.setItem('data', btoa(JSON.stringify(systemData, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v))); - localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, encFunc(JSON.stringify(sessionData))); + localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, btoa(JSON.stringify(sessionData))); console.debug('Session data saved'); @@ -892,12 +910,8 @@ export class GameData { }); } else { const data = localStorage.getItem(dataKey); - if (data) { - const decFunc = bypassLogin - ? (data: string) => atob(data) - : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8); - handleData(decFunc(data)); - } + if (data) + handleData(atob(data)); resolve(!!data); } }); @@ -965,7 +979,7 @@ export class GameData { return this.scene.ui.showText(`Your ${dataName} data could not be loaded. It may be corrupted.`, null, () => this.scene.ui.showText(null, 0), Utils.fixedInt(1500)); this.scene.ui.showText(`Your ${dataName} data will be overridden and the page will reload. Proceed?`, null, () => { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { - if (!bypassLogin && dataType < GameDataType.SETTINGS && localStorage.getItem(dataKey)) { + if (!bypassLogin && dataType < GameDataType.SETTINGS) { updateUserInfo().then(success => { if (!success) return displayError(`Could not contact the server. Your ${dataName} data could not be imported.`); @@ -976,15 +990,11 @@ export class GameData { console.error(error); return displayError(`An error occurred while updating ${dataName} data. Please contact the administrator.`); } - localStorage.removeItem(dataKey); window.location = window.location; }); }); } else { - const encFunc = bypassLogin || dataType === GameDataType.SETTINGS - ? (data: string) => btoa(data) - : (data: string) => AES.encrypt(data, saveKey); - localStorage.setItem(dataKey, encFunc(dataStr)); + localStorage.setItem(dataKey, btoa(dataStr)); window.location = window.location; } }, () => { From de3ca08704da84d78fc314064276cc2892f9f553 Mon Sep 17 00:00:00 2001 From: Douglas Marchione de Souza <42784723+Tiduzz@users.noreply.github.com> Date: Mon, 13 May 2024 22:09:46 -0300 Subject: [PATCH 23/27] Fix Air_Lock ability to express when it is switched in (#765) * Airlock ability now properly announces when it is in field when the pokemon with it is switched in * Set message as in the original games, also created a new attribute for in switch messages to not have the pokemon name required to be on it. * Committing language changes (i18n function) * Revert "Committing language changes (i18n function)" This reverts commit 2a3152003b676d54d21c5b675796fd2220b55b1d. * Changed message variable name --- src/data/ability.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 5ef07c39f7b..22867ee131f 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1407,6 +1407,23 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr { } } +export class PostSummonUnnamedMessageAbAttr extends PostSummonAbAttr { + //Attr doesn't force pokemon name on the message + private message: string; + + constructor(message: string) { + super(true); + + this.message = message; + } + + applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { + pokemon.scene.queueMessage(this.message); + + return true; + } +} + export class PostSummonAddBattlerTagAbAttr extends PostSummonAbAttr { private tagType: BattlerTagType; private turnCount: integer; @@ -3061,7 +3078,8 @@ export function initAbilities() { .attr(BlockCritAbAttr) .ignorable(), new Ability(Abilities.AIR_LOCK, 3) - .attr(SuppressWeatherEffectAbAttr, true), + .attr(SuppressWeatherEffectAbAttr, true) + .attr(PostSummonUnnamedMessageAbAttr, "The effects of the weather disappeared."), new Ability(Abilities.TANGLED_FEET, 4) .conditionalAttr(pokemon => !!pokemon.getTag(BattlerTagType.CONFUSED), BattleStatMultiplierAbAttr, BattleStat.EVA, 2) .ignorable(), From c42441294bf9d11afc0fbb018671e23bff0910d3 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Tue, 14 May 2024 03:17:41 +0200 Subject: [PATCH 24/27] Update French ability-trigger.ts (#836) --- src/locales/fr/ability-trigger.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/locales/fr/ability-trigger.ts b/src/locales/fr/ability-trigger.ts index 88900741218..f668ee5e8ab 100644 --- a/src/locales/fr/ability-trigger.ts +++ b/src/locales/fr/ability-trigger.ts @@ -1,5 +1,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const abilityTriggers: SimpleTranslationEntries = { - 'blockRecoilDamage' : `{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!`, -} as const; \ No newline at end of file + 'blockRecoilDamage' : `{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !`, +} as const; From 4e279224c59fe296c34fcdeaa6d304110d05552b Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Mon, 13 May 2024 20:59:38 -0500 Subject: [PATCH 25/27] Update Let's Go moves to their Gen 8 functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This primarily just affects Zippy Zap, as it loses its always crit attribute for an evasion increase (Associated localization strings will need updating). Also implemented Sparkly Swirl's status curing attribute. Also included is a wild evolution delay for some stone evolution Pokémon that was previously overlooked. --- src/data/move.ts | 4 ++-- src/data/pokemon-evolutions.ts | 4 ++-- src/locales/de/move.ts | 2 +- src/locales/en/move.ts | 2 +- src/locales/es/move.ts | 2 +- src/locales/fr/move.ts | 2 +- src/locales/it/move.ts | 2 +- src/locales/pt_BR/move.ts | 2 +- src/locales/zh_CN/move.ts | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 2b61d30b82c..6a6bee468a9 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -6221,7 +6221,7 @@ export function initMoves() { .ignoresVirtual(), /* End Unused */ new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 100, 2, 7) - .attr(CritOnlyAttr), + .attr(StatChangeAttr, BattleStat.EVA, 1, true), new AttackMove(Moves.SPLISHY_SPLASH, Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, 30, 0, 7) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -6246,7 +6246,7 @@ export function initMoves() { new AttackMove(Moves.FREEZY_FROST, Type.ICE, MoveCategory.SPECIAL, 100, 90, 10, -1, 0, 7) .attr(ResetStatsAttr), new AttackMove(Moves.SPARKLY_SWIRL, Type.FAIRY, MoveCategory.SPECIAL, 120, 85, 5, -1, 0, 7) - .partial(), + .attr(PartyStatusCureAttr, null, Abilities.NONE), new AttackMove(Moves.VEEVEE_VOLLEY, Type.NORMAL, MoveCategory.PHYSICAL, -1, -1, 20, -1, 0, 7) .attr(FriendshipPowerAttr), new AttackMove(Moves.DOUBLE_IRON_BASH, Type.STEEL, MoveCategory.PHYSICAL, 60, 100, 5, 30, 0, 7) diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index 23495b54ee2..7511b0e4162 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -1385,10 +1385,10 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.HELIOLISK, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.CHARJABUG]: [ - new SpeciesEvolution(Species.VIKAVOLT, 1, EvolutionItem.THUNDER_STONE, null) + new SpeciesEvolution(Species.VIKAVOLT, 1, EvolutionItem.THUNDER_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.CRABRAWLER]: [ - new SpeciesEvolution(Species.CRABOMINABLE, 1, EvolutionItem.ICE_STONE, null) + new SpeciesEvolution(Species.CRABOMINABLE, 1, EvolutionItem.ICE_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [Species.ROCKRUFF]: [ new SpeciesFormEvolution(Species.LYCANROC, '', 'midday', 25, null, new SpeciesEvolutionCondition(p => (p.scene.arena.getTimeOfDay() === TimeOfDay.DAWN || p.scene.arena.getTimeOfDay() === TimeOfDay.DAY) && (p.formIndex === 0)), null), diff --git a/src/locales/de/move.ts b/src/locales/de/move.ts index 1880253b838..a7750942e93 100644 --- a/src/locales/de/move.ts +++ b/src/locales/de/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, "zippyZap": { name: "Britzelturbo", - effect: "Ein stürmischer Blitz-Angriff mit hoher Erstschlag- und Volltrefferquote." + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness." }, "splishySplash": { name: "Plätschersurfer", diff --git a/src/locales/en/move.ts b/src/locales/en/move.ts index f0c1c623a05..11f92dda5a6 100644 --- a/src/locales/en/move.ts +++ b/src/locales/en/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, "zippyZap": { name: "Zippy Zap", - effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and results in a critical hit." + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness." }, "splishySplash": { name: "Splishy Splash", diff --git a/src/locales/es/move.ts b/src/locales/es/move.ts index 08aea3b456f..026e67b797f 100644 --- a/src/locales/es/move.ts +++ b/src/locales/es/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, zippyZap: { name: "Pikaturbo", - effect: "Ataque eléctrico a la velocidad del rayo. Este movimiento tiene prioridad alta y propina golpes críticos.", + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness.", }, splishySplash: { name: "Salpikasurf", diff --git a/src/locales/fr/move.ts b/src/locales/fr/move.ts index 2139f96d9a0..e148a6ff465 100644 --- a/src/locales/fr/move.ts +++ b/src/locales/fr/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, "zippyZap": { name: "Pika-Sprint", - effect: "Une attaque électrique rapide comme l’éclair qui inflige un coup critique à coup sûr. Frappe en priorité." + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness." }, "splishySplash": { name: "Pika-Splash", diff --git a/src/locales/it/move.ts b/src/locales/it/move.ts index 116a14b5d90..85babbfd36b 100644 --- a/src/locales/it/move.ts +++ b/src/locales/it/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, zippyZap: { name: "Sprintaboom", - effect: "Un attacco elettrico ad altissima velocità. Questa mossa ha priorità alta e infligge sicuramente un brutto colpo.", + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness.", }, splishySplash: { name: "Surfasplash", diff --git a/src/locales/pt_BR/move.ts b/src/locales/pt_BR/move.ts index 11fa8a240b9..97f24efee37 100644 --- a/src/locales/pt_BR/move.ts +++ b/src/locales/pt_BR/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, zippyZap: { name: "Zippy Zap", - effect: "O usuário ataca o alvo com rajadas de eletricidade em alta velocidade. Este movimento sempre ataca primeiro e resulta em um golpe crítico." + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness." }, splishySplash: { name: "Splishy Splash", diff --git a/src/locales/zh_CN/move.ts b/src/locales/zh_CN/move.ts index 3c4b8eb6243..1432fde5b7f 100644 --- a/src/locales/zh_CN/move.ts +++ b/src/locales/zh_CN/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, "zippyZap": { name: "电电加速", - effect: "迅猛无比的电击。必定能够\n先制攻击,击中对方的要害", + effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness.", }, "splishySplash": { name: "滔滔冲浪", From c0426cfe6b5b38bfc60459e3fe8c1835d450b24e Mon Sep 17 00:00:00 2001 From: Lugiad Date: Tue, 14 May 2024 04:19:28 +0200 Subject: [PATCH 26/27] Update French move.ts (#845) --- src/locales/fr/move.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/fr/move.ts b/src/locales/fr/move.ts index e148a6ff465..e4d7f5e03fa 100644 --- a/src/locales/fr/move.ts +++ b/src/locales/fr/move.ts @@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = { }, "zippyZap": { name: "Pika-Sprint", - effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness." + effect: "Une attaque électrique rapide comme l’éclair qui auguemente l’esquive. Frappe en priorité." }, "splishySplash": { name: "Pika-Splash", From fe7a4180a286a421e3b218f3432164796fbfa59f Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Mon, 13 May 2024 22:21:49 -0400 Subject: [PATCH 27/27] Give level 1 moves back that were made unusable in SV (#842) --- src/data/pokemon-level-moves.ts | 190 +++++++++++++++++++++++++++++++- 1 file changed, 188 insertions(+), 2 deletions(-) diff --git a/src/data/pokemon-level-moves.ts b/src/data/pokemon-level-moves.ts index 2823170b13d..4587753d110 100644 --- a/src/data/pokemon-level-moves.ts +++ b/src/data/pokemon-level-moves.ts @@ -322,6 +322,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ASSURANCE ], [ 1, Moves.PLUCK ], [ 1, Moves.DRILL_RUN ], + [ 1, Moves.PURSUIT ], [ 4, Moves.LEER ], [ 8, Moves.ASSURANCE ], [ 11, Moves.FURY_ATTACK ], @@ -566,6 +567,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CHARM ], [ 1, Moves.COPYCAT ], [ 1, Moves.DISARMING_VOICE ], + [ 1, Moves.SPOTLIGHT ], [ 4, Moves.STORED_POWER ], [ 8, Moves.ENCORE ], [ 12, Moves.AFTER_YOU ], @@ -600,6 +602,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.COPYCAT ], [ 1, Moves.AFTER_YOU ], [ 1, Moves.STORED_POWER ], + [ 1, Moves.SPOTLIGHT ], [ 1, Moves.DISARMING_VOICE ], ], [Species.VULPIX]: [ @@ -816,6 +819,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SUPERSONIC ], [ 1, Moves.DISABLE ], [ 1, Moves.QUIVER_DANCE ], + [ 1, Moves.SILVER_WIND ], [ 11, Moves.CONFUSION ], [ 13, Moves.POISON_POWDER ], [ 17, Moves.PSYBEAM ], @@ -850,6 +854,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TRI_ATTACK ], [ 1, Moves.ASTONISH ], [ 1, Moves.NIGHT_SLASH ], + [ 1, Moves.ROTOTILLER ], [ 12, Moves.MUD_SLAP ], [ 16, Moves.BULLDOZE ], [ 20, Moves.SUCKER_PUNCH ], @@ -895,6 +900,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.PSYDUCK]: [ [ 1, Moves.SCRATCH ], [ 1, Moves.TAIL_WHIP ], + [ 1, Moves.WATER_SPORT ], [ 3, Moves.WATER_GUN ], [ 6, Moves.CONFUSION ], [ 9, Moves.FURY_SWIPES ], @@ -914,6 +920,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.WATER_GUN ], [ 1, Moves.CONFUSION ], [ 1, Moves.AQUA_JET ], + [ 1, Moves.WATER_SPORT ], + [ 1, Moves.ME_FIRST ], [ 9, Moves.FURY_SWIPES ], [ 12, Moves.WATER_PULSE ], [ 15, Moves.DISABLE ], @@ -993,6 +1001,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.REVERSAL ], [ 1, Moves.CRUNCH ], [ 1, Moves.HELPING_HAND ], + [ 1, Moves.ODOR_SLEUTH ], [ 1, Moves.HOWL ], [ 1, Moves.FLARE_BLITZ ], [ 1, Moves.FIRE_FANG ], @@ -1003,6 +1012,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.POLIWAG]: [ [ 1, Moves.WATER_GUN ], [ 1, Moves.HYPNOSIS ], + [ 1, Moves.WATER_SPORT ], [ 6, Moves.POUND ], [ 12, Moves.MUD_SHOT ], [ 18, Moves.BUBBLE_BEAM ], @@ -1017,6 +1027,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.POUND ], [ 1, Moves.WATER_GUN ], [ 1, Moves.HYPNOSIS ], + [ 1, Moves.WATER_SPORT ], [ 1, Moves.MUD_SHOT ], [ 18, Moves.BUBBLE_BEAM ], [ 24, Moves.RAIN_DANCE ], @@ -1034,6 +1045,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.POUND ], [ 1, Moves.DOUBLE_EDGE ], [ 1, Moves.WATER_GUN ], + [ 1, Moves.WATER_SPORT ], [ 1, Moves.HYDRO_PUMP ], [ 1, Moves.BELLY_DRUM ], [ 1, Moves.RAIN_DANCE ], @@ -1098,6 +1110,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LOW_KICK ], [ 1, Moves.FOCUS_ENERGY ], [ 1, Moves.REVENGE ], + [ 1, Moves.KARATE_CHOP ], [ 12, Moves.LOW_SWEEP ], [ 16, Moves.KNOCK_OFF ], [ 20, Moves.SCARY_FACE ], @@ -1116,6 +1129,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FOCUS_ENERGY ], [ 1, Moves.REVENGE ], [ 1, Moves.WIDE_GUARD ], + [ 1, Moves.KARATE_CHOP ], [ 12, Moves.LOW_SWEEP ], [ 16, Moves.KNOCK_OFF ], [ 20, Moves.SCARY_FACE ], @@ -1195,6 +1209,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ACID ], [ 1, Moves.WATER_GUN ], [ 1, Moves.REFLECT_TYPE ], + [ 1, Moves.WRING_OUT ], [ 12, Moves.SUPERSONIC ], [ 16, Moves.WATER_PULSE ], [ 20, Moves.SCREECH ], @@ -1437,6 +1452,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GROWL ], [ 1, Moves.ICY_WIND ], [ 1, Moves.CHARM ], + [ 1, Moves.SIGNAL_BEAM ], [ 13, Moves.ENCORE ], [ 17, Moves.ICE_SHARD ], [ 21, Moves.REST ], @@ -1580,6 +1596,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.ROCK_THROW ], [ 1, Moves.HARDEN ], + [ 1, Moves.MUD_SPORT ], [ 4, Moves.SMACK_DOWN ], [ 8, Moves.ROCK_POLISH ], [ 12, Moves.DRAGON_BREATH ], @@ -1617,6 +1634,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CONFUSION ], [ 1, Moves.HYPNOSIS ], [ 1, Moves.SWITCHEROO ], + [ 1, Moves.NIGHTMARE ], [ 13, Moves.HEADBUTT ], [ 17, Moves.POISON_GAS ], [ 21, Moves.PSYBEAM ], @@ -1631,6 +1649,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.KRABBY]: [ [ 1, Moves.LEER ], [ 1, Moves.WATER_GUN ], + [ 1, Moves.MUD_SPORT ], [ 4, Moves.HARDEN ], [ 8, Moves.METAL_CLAW ], [ 12, Moves.MUD_SHOT ], @@ -1651,6 +1670,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.METAL_CLAW ], [ 1, Moves.HAMMER_ARM ], [ 1, Moves.WIDE_GUARD ], + [ 1, Moves.MUD_SPORT ], [ 12, Moves.MUD_SHOT ], [ 16, Moves.PROTECT ], [ 20, Moves.BUBBLE_BEAM ], @@ -1704,6 +1724,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.EXEGGCUTE]: [ [ 1, Moves.ABSORB ], [ 1, Moves.HYPNOSIS ], + [ 1, Moves.BARRAGE ], [ 5, Moves.REFLECT ], [ 10, Moves.LEECH_SEED ], [ 15, Moves.MEGA_DRAIN ], @@ -1718,6 +1739,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.EXEGGUTOR]: [ [ 0, Moves.STOMP ], + [ 1, Moves.BARRAGE ], [ 1, Moves.SEED_BOMB ], [ 1, Moves.PSYSHOCK ], [ 1, Moves.WOOD_HAMMER ], @@ -1758,6 +1780,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GROWL ], [ 1, Moves.MUD_SLAP ], [ 1, Moves.FALSE_SWIPE ], + [ 1, Moves.BONE_CLUB ], [ 12, Moves.HEADBUTT ], [ 16, Moves.RETALIATE ], [ 20, Moves.FLING ], @@ -1777,6 +1800,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.HELPING_HAND ], [ 1, Moves.FEINT ], [ 1, Moves.LOW_SWEEP ], + [ 1, Moves.JUMP_KICK ], + [ 1, Moves.ROLLING_KICK ], [ 4, Moves.DOUBLE_KICK ], [ 8, Moves.LOW_KICK ], [ 12, Moves.ENDURE ], @@ -1797,6 +1822,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FAKE_OUT ], [ 1, Moves.HELPING_HAND ], [ 1, Moves.FEINT ], + [ 1, Moves.PURSUIT ], + [ 1, Moves.COMET_PUNCH ], [ 4, Moves.MACH_PUNCH ], [ 8, Moves.VACUUM_WAVE ], [ 12, Moves.DETECT ], @@ -1920,6 +1947,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.TANGELA]: [ [ 1, Moves.BIND ], [ 1, Moves.ABSORB ], + [ 1, Moves.CONSTRICT ], [ 4, Moves.STUN_SPORE ], [ 8, Moves.GROWTH ], [ 12, Moves.MEGA_DRAIN ], @@ -1939,6 +1967,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.KANGASKHAN]: [ [ 1, Moves.POUND ], [ 1, Moves.TAIL_WHIP ], + [ 1, Moves.COMET_PUNCH ], [ 4, Moves.GROWL ], [ 8, Moves.FAKE_OUT ], [ 12, Moves.BITE ], @@ -1986,6 +2015,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.GOLDEEN]: [ [ 1, Moves.TAIL_WHIP ], [ 1, Moves.PECK ], + [ 1, Moves.WATER_SPORT ], [ 5, Moves.SUPERSONIC ], [ 10, Moves.WATER_PULSE ], [ 15, Moves.HORN_ATTACK ], @@ -2000,6 +2030,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SEAKING]: [ [ 1, Moves.TAIL_WHIP ], [ 1, Moves.SUPERSONIC ], + [ 1, Moves.WATER_SPORT ], [ 1, Moves.PECK ], [ 1, Moves.WATER_PULSE ], [ 15, Moves.HORN_ATTACK ], @@ -2042,6 +2073,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CONFUSE_RAY ], [ 1, Moves.LIGHT_SCREEN ], [ 1, Moves.SWIFT ], + [ 1, Moves.SPOTLIGHT ], [ 1, Moves.RAPID_SPIN ], [ 1, Moves.COSMIC_POWER ], [ 1, Moves.BRINE ], @@ -2056,6 +2088,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GUARD_SWAP ], [ 1, Moves.WIDE_GUARD ], [ 1, Moves.QUICK_GUARD ], + [ 1, Moves.BARRIER ], [ 12, Moves.CONFUSION ], [ 16, Moves.ROLE_PLAY ], [ 20, Moves.PROTECT ], @@ -2334,6 +2367,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.OMANYTE]: [ [ 1, Moves.BIND ], [ 1, Moves.WITHDRAW ], + [ 1, Moves.CONSTRICT ], [ 5, Moves.ROLLOUT ], [ 10, Moves.SAND_ATTACK ], [ 15, Moves.WATER_GUN ], @@ -2351,6 +2385,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 0, Moves.CRUNCH ], [ 1, Moves.BIND ], [ 1, Moves.SAND_ATTACK ], + [ 1, Moves.CONSTRICT ], + [ 1, Moves.SPIKE_CANNON ], [ 1, Moves.WITHDRAW ], [ 1, Moves.ROLLOUT ], [ 15, Moves.WATER_GUN ], @@ -2841,6 +2877,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SPINARAK]: [ [ 1, Moves.POISON_STING ], [ 1, Moves.STRING_SHOT ], + [ 1, Moves.CONSTRICT ], [ 5, Moves.ABSORB ], [ 8, Moves.INFESTATION ], [ 12, Moves.SCARY_FACE ], @@ -2861,6 +2898,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.POISON_STING ], [ 1, Moves.ABSORB ], [ 1, Moves.STRING_SHOT ], + [ 1, Moves.CONSTRICT ], [ 1, Moves.FOCUS_ENERGY ], [ 1, Moves.BUG_BITE ], [ 1, Moves.FELL_STINGER ], @@ -2918,6 +2956,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 0, Moves.SWALLOW ], [ 1, Moves.SUPERSONIC ], [ 1, Moves.WATER_GUN ], + [ 1, Moves.SPOTLIGHT ], [ 1, Moves.THUNDER_WAVE ], [ 1, Moves.ELECTRO_BALL ], [ 1, Moves.EERIE_IMPULSE ], @@ -3069,6 +3108,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ZAP_CANNON ], [ 1, Moves.DRAGON_PULSE ], [ 1, Moves.MAGNETIC_FLUX ], + [ 1, Moves.ION_DELUGE ], [ 11, Moves.COTTON_SPORE ], [ 16, Moves.CHARGE ], [ 20, Moves.TAKE_DOWN ], @@ -3371,6 +3411,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.HELPING_HAND ], [ 1, Moves.COVET ], [ 1, Moves.COPYCAT ], + [ 1, Moves.PURSUIT ], [ 5, Moves.SAND_ATTACK ], [ 10, Moves.SNARL ], [ 15, Moves.QUICK_ATTACK ], @@ -3425,6 +3466,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.MISDREAVUS]: [ [ 1, Moves.GROWL ], [ 1, Moves.CONFUSION ], + [ 1, Moves.PSYWAVE ], [ 10, Moves.ASTONISH ], [ 14, Moves.CONFUSE_RAY ], [ 19, Moves.MEAN_LOOK ], @@ -3492,6 +3534,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TOXIC_SPIKES ], [ 1, Moves.MAGNET_RISE ], [ 1, Moves.BUG_BITE ], + [ 1, Moves.MIRROR_SHOT ], [ 12, Moves.TAKE_DOWN ], [ 17, Moves.RAPID_SPIN ], [ 20, Moves.ROLLOUT ], @@ -3541,6 +3584,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.ROCK_THROW ], [ 1, Moves.HARDEN ], + [ 1, Moves.MUD_SPORT ], [ 1, Moves.CRUNCH ], [ 1, Moves.ROCK_POLISH ], [ 1, Moves.THUNDER_FANG ], @@ -3638,6 +3682,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SHUCKLE]: [ [ 1, Moves.WRAP ], [ 1, Moves.WITHDRAW ], + [ 1, Moves.BIDE ], + [ 1, Moves.CONSTRICT ], [ 5, Moves.ROLLOUT ], [ 10, Moves.STRUGGLE_BUG ], [ 15, Moves.ROCK_THROW ], @@ -3758,6 +3804,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SWINUB]: [ [ 1, Moves.TACKLE ], [ 1, Moves.MUD_SLAP ], + [ 1, Moves.ODOR_SLEUTH ], [ 5, Moves.POWDER_SNOW ], [ 10, Moves.FLAIL ], [ 15, Moves.ICE_SHARD ], @@ -3775,6 +3822,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FLAIL ], [ 1, Moves.POWDER_SNOW ], [ 1, Moves.MUD_SLAP ], + [ 1, Moves.ODOR_SLEUTH ], [ 1, Moves.ANCIENT_POWER ], [ 15, Moves.ICE_SHARD ], [ 20, Moves.MIST ], @@ -3819,6 +3867,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.OCTILLERY]: [ [ 0, Moves.OCTAZOOKA ], [ 1, Moves.WRAP ], + [ 1, Moves.CONSTRICT ], [ 1, Moves.WATER_GUN ], [ 1, Moves.FOCUS_ENERGY ], [ 1, Moves.HELPING_HAND ], @@ -3845,6 +3894,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SUPERSONIC ], [ 1, Moves.WATER_GUN ], [ 1, Moves.PSYBEAM ], + [ 1, Moves.SIGNAL_BEAM ], [ 1, Moves.BULLET_SEED ], [ 1, Moves.ROOST ], [ 12, Moves.WATER_PULSE ], @@ -3934,6 +3984,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], [ 1, Moves.DEFENSE_CURL ], + [ 1, Moves.ODOR_SLEUTH ], [ 6, Moves.FLAIL ], [ 10, Moves.ROLLOUT ], [ 15, Moves.BULLDOZE ], @@ -3981,6 +4032,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.STANTLER]: [ [ 1, Moves.TACKLE ], + [ 1, Moves.ME_FIRST ], [ 3, Moves.LEER ], [ 7, Moves.ASTONISH ], [ 10, Moves.HYPNOSIS ], @@ -4015,6 +4067,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FAKE_OUT ], [ 1, Moves.HELPING_HAND ], [ 1, Moves.FEINT ], + [ 1, Moves.PURSUIT ], + [ 1, Moves.ROLLING_KICK ], [ 4, Moves.QUICK_ATTACK ], [ 8, Moves.GYRO_BALL ], [ 12, Moves.DETECT ], @@ -4334,6 +4388,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.X_SCISSOR ], [ 1, Moves.ENERGY_BALL ], [ 1, Moves.SHED_TAIL ], + [ 1, Moves.DUAL_CHOP ], [ 5, Moves.MEGA_DRAIN ], [ 12, Moves.DETECT ], [ 15, Moves.QUICK_GUARD ], @@ -4524,6 +4579,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GROWL ], [ 1, Moves.SWITCHEROO ], [ 1, Moves.BABY_DOLL_EYES ], + [ 1, Moves.ROTOTILLER ], [ 9, Moves.COVET ], [ 12, Moves.HEADBUTT ], [ 15, Moves.HONE_CLAWS ], @@ -4644,6 +4700,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SEEDOT]: [ [ 1, Moves.TACKLE ], [ 1, Moves.HARDEN ], + [ 1, Moves.BIDE ], [ 3, Moves.ABSORB ], [ 6, Moves.ASTONISH ], [ 9, Moves.GROWTH ], @@ -4756,6 +4813,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.WATER_GUN ], [ 1, Moves.TAILWIND ], [ 1, Moves.SUPERSONIC ], + [ 1, Moves.WATER_SPORT ], [ 15, Moves.WING_ATTACK ], [ 20, Moves.WATER_PULSE ], [ 28, Moves.STOCKPILE ], @@ -4842,6 +4900,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.QUICK_ATTACK ], [ 1, Moves.SWEET_SCENT ], [ 1, Moves.SOAK ], + [ 1, Moves.OMINOUS_WIND ], [ 17, Moves.GUST ], [ 22, Moves.SCARY_FACE ], [ 22, Moves.AIR_CUTTER ], @@ -5232,6 +5291,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.MEDITITE]: [ [ 1, Moves.CONFUSION ], [ 1, Moves.WORK_UP ], + [ 1, Moves.BIDE ], [ 9, Moves.DETECT ], [ 12, Moves.ENDURE ], [ 15, Moves.FEINT ], @@ -5254,6 +5314,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CONFUSION ], [ 1, Moves.DETECT ], [ 1, Moves.WORK_UP ], + [ 1, Moves.BIDE ], [ 12, Moves.ENDURE ], [ 15, Moves.FEINT ], [ 17, Moves.FORCE_PALM ], @@ -5345,6 +5406,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 49, Moves.ENTRAINMENT ], ], [Species.VOLBEAT]: [ + [ 1, Moves.FLASH ], [ 1, Moves.TACKLE ], [ 5, Moves.DOUBLE_TEAM ], [ 8, Moves.CONFUSE_RAY ], @@ -5420,6 +5482,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.POUND ], [ 1, Moves.YAWN ], [ 1, Moves.POISON_GAS ], + [ 1, Moves.WRING_OUT ], [ 1, Moves.SLUDGE ], [ 12, Moves.AMNESIA ], [ 17, Moves.ACID_SPRAY ], @@ -5606,6 +5669,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.TRAPINCH]: [ [ 1, Moves.SAND_ATTACK ], [ 1, Moves.ASTONISH ], + [ 1, Moves.BIDE ], + [ 1, Moves.FEINT_ATTACK ], [ 8, Moves.BITE ], [ 12, Moves.MUD_SLAP ], [ 16, Moves.SAND_TOMB ], @@ -5629,6 +5694,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SUPERPOWER ], [ 1, Moves.ASTONISH ], [ 1, Moves.BULLDOZE ], + [ 1, Moves.BIDE ], + [ 1, Moves.FEINT_ATTACK ], [ 12, Moves.MUD_SLAP ], [ 16, Moves.SAND_TOMB ], [ 20, Moves.DRAGON_TAIL ], @@ -5655,6 +5722,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ASTONISH ], [ 1, Moves.DRAGON_DANCE ], [ 1, Moves.FEINT ], + [ 1, Moves.BIDE ], + [ 1, Moves.FEINT_ATTACK ], [ 12, Moves.MUD_SLAP ], [ 16, Moves.SAND_TOMB ], [ 20, Moves.DRAGON_TAIL ], @@ -5932,6 +6001,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.LILEEP]: [ [ 1, Moves.WRAP ], [ 1, Moves.ASTONISH ], + [ 1, Moves.CONSTRICT ], [ 4, Moves.ACID ], [ 8, Moves.CONFUSE_RAY ], [ 12, Moves.INGRAIN ], @@ -5950,6 +6020,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEECH_SEED ], [ 1, Moves.WRAP ], [ 1, Moves.ASTONISH ], + [ 1, Moves.CONSTRICT ], [ 1, Moves.ACID ], [ 1, Moves.CONFUSE_RAY ], [ 12, Moves.INGRAIN ], @@ -6006,6 +6077,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.WRAP ], [ 1, Moves.WATER_GUN ], + [ 1, Moves.WATER_SPORT ], [ 4, Moves.DISARMING_VOICE ], [ 8, Moves.TWISTER ], [ 12, Moves.AQUA_RING ], @@ -6145,6 +6217,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GROWL ], [ 1, Moves.ASTONISH ], [ 1, Moves.CONFUSION ], + [ 1, Moves.SYNCHRONOISE ], [ 13, Moves.YAWN ], [ 16, Moves.STORED_POWER ], [ 19, Moves.TAKE_DOWN ], @@ -6204,7 +6277,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.HEADBUTT ], [ 1, Moves.ASTONISH ], [ 1, Moves.LEER ], - [ 1, Moves.DOUBLE_TEAM ], + [ 1, Moves.DOUBLE_TEAM ], + [ 1, Moves.ICE_BALL ], [ 15, Moves.ICE_SHARD ], [ 20, Moves.PROTECT ], [ 25, Moves.ICY_WIND ], @@ -6272,6 +6346,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 72, Moves.SHEER_COLD ], ], [Species.CLAMPERL]: [ + [ 1, Moves.CLAMP ], [ 1, Moves.WATER_GUN ], [ 1, Moves.WHIRLPOOL ], [ 1, Moves.IRON_DEFENSE ], @@ -6495,6 +6570,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.LATIAS]: [ [ 1, Moves.STORED_POWER ], [ 1, Moves.CHARM ], + [ 1, Moves.PSYWAVE ], [ 5, Moves.HELPING_HAND ], [ 10, Moves.RECOVER ], [ 15, Moves.CONFUSION ], @@ -6513,6 +6589,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.LATIOS]: [ [ 1, Moves.STORED_POWER ], [ 1, Moves.DRAGON_DANCE ], + [ 1, Moves.HEAL_BLOCK ], + [ 1, Moves.PSYWAVE ], [ 5, Moves.HELPING_HAND ], [ 10, Moves.RECOVER ], [ 15, Moves.CONFUSION ], @@ -6831,6 +6909,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.KRICKETOT]: [ [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], + [ 1, Moves.BIDE ], [ 6, Moves.STRUGGLE_BUG ], [ 16, Moves.BUG_BITE ], ], @@ -6838,6 +6917,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 0, Moves.FURY_CUTTER ], [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], + [ 1, Moves.BIDE ], [ 14, Moves.ABSORB ], [ 18, Moves.SING ], [ 22, Moves.FOCUS_ENERGY ], @@ -7055,11 +7135,13 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 36, Moves.TOXIC ], [ 40, Moves.ATTACK_ORDER ], [ 40, Moves.DEFEND_ORDER ], + [ 40, Moves.HEAL_ORDER ], [ 44, Moves.DESTINY_BOND ], ], [Species.PACHIRISU]: [ [ 1, Moves.GROWL ], [ 1, Moves.THUNDER_SHOCK ], + [ 1, Moves.BIDE ], [ 5, Moves.QUICK_ATTACK ], [ 9, Moves.CHARM ], [ 13, Moves.SPARK ], @@ -7156,6 +7238,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.RECOVER ], [ 1, Moves.HARDEN ], [ 1, Moves.MUD_SLAP ], + [ 1, Moves.MUD_SPORT ], [ 15, Moves.WATER_PULSE ], [ 20, Moves.ANCIENT_POWER ], [ 25, Moves.BODY_SLAM ], @@ -7183,6 +7266,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.DRIFLOON]: [ [ 1, Moves.MINIMIZE ], [ 1, Moves.ASTONISH ], + [ 1, Moves.CONSTRICT ], [ 4, Moves.GUST ], [ 8, Moves.FOCUS_ENERGY ], [ 12, Moves.PAYBACK ], @@ -7203,6 +7287,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.MINIMIZE ], [ 1, Moves.FOCUS_ENERGY ], [ 1, Moves.ASTONISH ], + [ 1, Moves.CONSTRICT ], [ 1, Moves.STRENGTH_SAP ], [ 12, Moves.PAYBACK ], [ 16, Moves.HEX ], @@ -7217,6 +7302,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 54, Moves.EXPLOSION ], ], [Species.BUNEARY]: [ + [ 1, Moves.FRUSTRATION ], [ 1, Moves.POUND ], [ 1, Moves.SPLASH ], [ 4, Moves.DEFENSE_CURL ], @@ -7234,12 +7320,14 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 52, Moves.HEALING_WISH ], ], [Species.LOPUNNY]: [ + [ 0, Moves.RETURN ], [ 1, Moves.POUND ], [ 1, Moves.DEFENSE_CURL ], [ 1, Moves.SPLASH ], [ 1, Moves.MIRROR_COAT ], [ 1, Moves.MAGIC_COAT ], [ 1, Moves.BABY_DOLL_EYES ], + [ 1, Moves.ROTOTILLER ], [ 12, Moves.AFTER_YOU ], [ 16, Moves.QUICK_ATTACK ], [ 20, Moves.DOUBLE_KICK ], @@ -7256,6 +7344,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.MISMAGIUS]: [ [ 1, Moves.GROWL ], [ 1, Moves.SPITE ], + [ 1, Moves.PSYWAVE ], + [ 1, Moves.LUCKY_CHANT ], [ 1, Moves.ASTONISH ], [ 1, Moves.MAGICAL_LEAF ], [ 1, Moves.POWER_GEM ], @@ -7269,6 +7359,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SUCKER_PUNCH ], [ 1, Moves.NIGHT_SLASH ], [ 1, Moves.QUASH ], + [ 1, Moves.PURSUIT ], [ 25, Moves.SWAGGER ], [ 35, Moves.NASTY_PLOT ], [ 45, Moves.FOUL_PLAY ], @@ -7409,6 +7500,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.MIME_JR]: [ [ 1, Moves.POUND ], [ 1, Moves.COPYCAT ], + [ 1, Moves.BARRIER ], [ 4, Moves.BATON_PASS ], [ 8, Moves.ENCORE ], [ 12, Moves.CONFUSION ], @@ -7455,6 +7547,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SPIRITOMB]: [ [ 1, Moves.NIGHT_SHADE ], [ 1, Moves.CONFUSE_RAY ], + [ 1, Moves.PURSUIT ], [ 5, Moves.SHADOW_SNEAK ], [ 10, Moves.SPITE ], [ 15, Moves.PAYBACK ], @@ -7487,6 +7580,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.DRAGON_BREATH ], [ 1, Moves.SAND_TOMB ], + [ 1, Moves.DUAL_CHOP ], [ 18, Moves.BULLDOZE ], [ 27, Moves.BITE ], [ 34, Moves.SLASH ], @@ -7502,6 +7596,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.DRAGON_BREATH ], [ 1, Moves.SAND_TOMB ], + [ 1, Moves.DUAL_CHOP ], [ 18, Moves.BULLDOZE ], [ 27, Moves.BITE ], [ 34, Moves.SLASH ], @@ -7514,6 +7609,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.MUNCHLAX]: [ [ 1, Moves.TACKLE ], [ 1, Moves.LICK ], + [ 1, Moves.ODOR_SLEUTH ], [ 4, Moves.DEFENSE_CURL ], [ 8, Moves.RECYCLE ], [ 12, Moves.COVET ], @@ -7789,6 +7885,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TAUNT ], [ 1, Moves.ASSURANCE ], [ 1, Moves.ICE_SHARD ], + [ 1, Moves.EMBARGO ], [ 18, Moves.METAL_CLAW ], [ 24, Moves.ICY_WIND ], [ 30, Moves.FURY_SWIPES ], @@ -7804,6 +7901,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SUPERSONIC ], [ 1, Moves.THUNDER_SHOCK ], [ 1, Moves.THUNDER_WAVE ], + [ 1, Moves.BARRIER ], [ 1, Moves.TRI_ATTACK ], [ 1, Moves.MIRROR_COAT ], [ 1, Moves.MAGNETIC_FLUX ], @@ -7825,6 +7923,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.DEFENSE_CURL ], [ 1, Moves.LICK ], [ 1, Moves.ROLLOUT ], + [ 1, Moves.WRING_OUT ], [ 6, Moves.REST ], [ 18, Moves.WRAP ], [ 24, Moves.DISABLE ], @@ -7859,6 +7958,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GROWTH ], [ 1, Moves.STUN_SPORE ], [ 1, Moves.BLOCK ], + [ 1, Moves.CONSTRICT ], [ 12, Moves.MEGA_DRAIN ], [ 16, Moves.VINE_WHIP ], [ 20, Moves.POISON_POWDER ], @@ -7878,6 +7978,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.THUNDER_SHOCK ], [ 1, Moves.QUICK_ATTACK ], [ 1, Moves.CHARGE ], + [ 1, Moves.ION_DELUGE ], [ 12, Moves.SWIFT ], [ 16, Moves.SHOCK_WAVE ], [ 20, Moves.THUNDER_WAVE ], @@ -8024,6 +8125,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FLAIL ], [ 1, Moves.POWDER_SNOW ], [ 1, Moves.MUD_SLAP ], + [ 1, Moves.ODOR_SLEUTH ], [ 1, Moves.ANCIENT_POWER ], [ 1, Moves.ICE_FANG ], [ 15, Moves.ICE_SHARD ], @@ -8147,6 +8249,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CRUNCH ], [ 1, Moves.ASTONISH ], [ 1, Moves.ICE_FANG ], + [ 1, Moves.OMINOUS_WIND ], [ 15, Moves.ICE_SHARD ], [ 20, Moves.DRAINING_KISS ], [ 25, Moves.ICY_WIND ], @@ -8269,6 +8372,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.REGIGIGAS]: [ [ 1, Moves.POUND ], [ 1, Moves.CONFUSE_RAY ], + [ 1, Moves.DIZZY_PUNCH ], + [ 1, Moves.FORESIGHT ], [ 6, Moves.PAYBACK ], [ 12, Moves.REVENGE ], [ 18, Moves.STOMP ], @@ -8346,6 +8451,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.DARKRAI]: [ [ 1, Moves.DISABLE ], + [ 1, Moves.OMINOUS_WIND ], [ 11, Moves.QUICK_ATTACK ], [ 20, Moves.HYPNOSIS ], [ 29, Moves.SUCKER_PUNCH ], @@ -8374,6 +8480,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.ARCEUS]: [ [ 1, Moves.SEISMIC_TOSS ], [ 1, Moves.COSMIC_POWER ], + [ 1, Moves.PUNISHMENT ], [ 10, Moves.GRAVITY ], [ 20, Moves.EARTH_POWER ], [ 30, Moves.HYPER_VOICE ], @@ -8667,6 +8774,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 40, Moves.PLAY_ROUGH ], ], [Species.LIEPARD]: [ + [ 1, Moves.ASSIST ], [ 1, Moves.SCRATCH ], [ 1, Moves.SAND_ATTACK ], [ 1, Moves.GROWL ], @@ -8755,6 +8863,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.MUNNA]: [ [ 1, Moves.DEFENSE_CURL ], [ 1, Moves.STORED_POWER ], + [ 1, Moves.PSYWAVE ], [ 4, Moves.HYPNOSIS ], [ 8, Moves.PSYBEAM ], [ 12, Moves.IMPRISON ], @@ -8774,6 +8883,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.PSYCHIC ], [ 1, Moves.HYPNOSIS ], [ 1, Moves.DEFENSE_CURL ], + [ 1, Moves.LUCKY_CHANT ], [ 1, Moves.DREAM_EATER ], [ 1, Moves.MOONLIGHT ], [ 1, Moves.FUTURE_SIGHT ], @@ -8851,6 +8961,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.THUNDER_WAVE ], [ 1, Moves.QUICK_ATTACK ], [ 1, Moves.CHARGE ], + [ 1, Moves.ION_DELUGE ], [ 11, Moves.SHOCK_WAVE ], [ 18, Moves.FLAME_CHARGE ], [ 25, Moves.SPARK ], @@ -8940,6 +9051,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.DRILBUR]: [ [ 1, Moves.MUD_SLAP ], [ 1, Moves.RAPID_SPIN ], + [ 1, Moves.MUD_SPORT ], [ 4, Moves.SCRATCH ], [ 8, Moves.HONE_CLAWS ], [ 12, Moves.FURY_SWIPES ], @@ -8958,6 +9070,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SCRATCH ], [ 1, Moves.MUD_SLAP ], [ 1, Moves.RAPID_SPIN ], + [ 1, Moves.MUD_SPORT ], + [ 1, Moves.ROTOTILLER ], [ 1, Moves.HONE_CLAWS ], [ 12, Moves.FURY_SWIPES ], [ 16, Moves.METAL_CLAW ], @@ -9010,6 +9124,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.LOW_KICK ], [ 1, Moves.ROCK_THROW ], + [ 1, Moves.BIDE ], [ 12, Moves.FOCUS_ENERGY ], [ 16, Moves.BULK_UP ], [ 20, Moves.ROCK_SLIDE ], @@ -9026,6 +9141,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.LOW_KICK ], [ 1, Moves.ROCK_THROW ], + [ 1, Moves.BIDE ], [ 12, Moves.FOCUS_ENERGY ], [ 16, Moves.BULK_UP ], [ 20, Moves.ROCK_SLIDE ], @@ -9090,6 +9206,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.THROH]: [ [ 1, Moves.BIND ], [ 1, Moves.LEER ], + [ 1, Moves.BIDE ], + [ 1, Moves.MAT_BLOCK ], [ 5, Moves.FOCUS_ENERGY ], [ 10, Moves.CIRCLE_THROW ], [ 15, Moves.WIDE_GUARD ], @@ -9105,6 +9223,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SAWK]: [ [ 1, Moves.LEER ], [ 1, Moves.ROCK_SMASH ], + [ 1, Moves.BIDE ], [ 5, Moves.FOCUS_ENERGY ], [ 10, Moves.DOUBLE_KICK ], [ 15, Moves.QUICK_GUARD ], @@ -9134,6 +9253,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.RAZOR_LEAF ], [ 1, Moves.STRING_SHOT ], [ 1, Moves.BUG_BITE ], + [ 1, Moves.GRASS_WHISTLE ], [ 22, Moves.STRUGGLE_BUG ], [ 29, Moves.ENDURE ], [ 31, Moves.STICKY_WEB ], @@ -9466,6 +9586,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.LOW_KICK ], [ 1, Moves.PAYBACK ], + [ 1, Moves.FEINT_ATTACK ], [ 12, Moves.SAND_ATTACK ], [ 16, Moves.FACADE ], [ 20, Moves.PROTECT ], @@ -9538,6 +9659,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.TIRTOUGA]: [ [ 1, Moves.WATER_GUN ], [ 1, Moves.WITHDRAW ], + [ 1, Moves.BIDE ], [ 3, Moves.PROTECT ], [ 6, Moves.AQUA_JET ], [ 9, Moves.SMACK_DOWN ], @@ -9559,6 +9681,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.WITHDRAW ], [ 1, Moves.PROTECT ], [ 1, Moves.AQUA_JET ], + [ 1, Moves.BIDE ], [ 9, Moves.SMACK_DOWN ], [ 12, Moves.ANCIENT_POWER ], [ 15, Moves.BITE ], @@ -9674,6 +9797,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TORMENT ], [ 1, Moves.U_TURN ], [ 1, Moves.HONE_CLAWS ], + [ 1, Moves.PURSUIT ], [ 12, Moves.FURY_SWIPES ], [ 20, Moves.TAUNT ], [ 24, Moves.KNOCK_OFF ], @@ -9771,6 +9895,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.SOLOSIS]: [ [ 1, Moves.CONFUSION ], [ 1, Moves.PROTECT ], + [ 1, Moves.PSYWAVE ], [ 4, Moves.RECOVER ], [ 8, Moves.ENDEAVOR ], [ 12, Moves.PSYBEAM ], @@ -9789,8 +9914,10 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.DUOSION]: [ [ 1, Moves.CONFUSION ], [ 1, Moves.RECOVER ], + [ 1, Moves.PSYWAVE ], [ 1, Moves.PROTECT ], [ 1, Moves.ENDEAVOR ], + [ 1, Moves.SNATCH ], [ 12, Moves.PSYBEAM ], [ 16, Moves.CHARM ], [ 20, Moves.PSYSHOCK ], @@ -9810,6 +9937,9 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.RECOVER ], [ 1, Moves.PROTECT ], [ 1, Moves.ENDEAVOR ], + [ 1, Moves.DIZZY_PUNCH ], + [ 1, Moves.PSYWAVE ], + [ 1, Moves.SNATCH ], [ 12, Moves.PSYBEAM ], [ 16, Moves.CHARM ], [ 20, Moves.PSYSHOCK ], @@ -9908,6 +10038,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.DEERLING]: [ [ 1, Moves.TACKLE ], + [ 1, Moves.CAMOUFLAGE ], [ 4, Moves.GROWL ], [ 7, Moves.SAND_ATTACK ], [ 10, Moves.DOUBLE_KICK ], @@ -9925,6 +10056,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SAND_ATTACK ], [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], + [ 1, Moves.CAMOUFLAGE ], [ 1, Moves.MEGAHORN ], [ 10, Moves.DOUBLE_KICK ], [ 13, Moves.LEECH_SEED ], @@ -9978,6 +10110,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FURY_CUTTER ], [ 1, Moves.QUICK_GUARD ], [ 1, Moves.FELL_STINGER ], + [ 1, Moves.TWINEEDLE ], [ 12, Moves.FALSE_SWIPE ], [ 16, Moves.ACID_SPRAY ], [ 20, Moves.HEADBUTT ], @@ -10011,6 +10144,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.GROWTH ], [ 1, Moves.STUN_SPORE ], [ 1, Moves.ASTONISH ], + [ 1, Moves.BIDE ], [ 12, Moves.MEGA_DRAIN ], [ 16, Moves.SYNTHESIS ], [ 20, Moves.CLEAR_SMOG ], @@ -10025,6 +10159,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.FRILLISH]: [ [ 1, Moves.WATER_GUN ], [ 1, Moves.ABSORB ], + [ 1, Moves.WATER_SPORT ], [ 4, Moves.POISON_STING ], [ 8, Moves.NIGHT_SHADE ], [ 12, Moves.WATER_PULSE ], @@ -10041,6 +10176,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.JELLICENT]: [ [ 1, Moves.POISON_STING ], [ 1, Moves.WATER_GUN ], + [ 1, Moves.WATER_SPORT ], + [ 1, Moves.WRING_OUT ], [ 1, Moves.ABSORB ], [ 1, Moves.NIGHT_SHADE ], [ 1, Moves.ACID_ARMOR ], @@ -10058,6 +10195,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.ALOMOMOLA]: [ [ 1, Moves.POUND ], [ 1, Moves.PLAY_NICE ], + [ 1, Moves.WATER_SPORT ], [ 5, Moves.AQUA_RING ], [ 9, Moves.AQUA_JET ], [ 13, Moves.HELPING_HAND ], @@ -10075,6 +10213,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.JOLTIK]: [ [ 1, Moves.ABSORB ], [ 1, Moves.FURY_CUTTER ], + [ 1, Moves.SPIDER_WEB ], [ 4, Moves.ELECTROWEB ], [ 8, Moves.BUG_BITE ], [ 12, Moves.STRING_SHOT ], @@ -10094,6 +10233,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FURY_CUTTER ], [ 1, Moves.BUG_BITE ], [ 1, Moves.ELECTROWEB ], + [ 1, Moves.SPIDER_WEB ], [ 12, Moves.STRING_SHOT ], [ 16, Moves.THUNDER_WAVE ], [ 20, Moves.ELECTRO_BALL ], @@ -10125,6 +10265,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.PIN_MISSILE ], [ 1, Moves.HARDEN ], [ 1, Moves.METAL_CLAW ], + [ 1, Moves.ROCK_CLIMB ], [ 15, Moves.INGRAIN ], [ 20, Moves.FLASH_CANNON ], [ 25, Moves.IRON_HEAD ], @@ -10197,6 +10338,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.THUNDER_WAVE ], [ 1, Moves.SPARK ], [ 1, Moves.CHARGE_BEAM ], + [ 1, Moves.ION_DELUGE ], [ 9, Moves.BIND ], [ 19, Moves.ACID ], [ 29, Moves.DISCHARGE ], @@ -10239,6 +10381,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.BEHEEYEM]: [ [ 1, Moves.GROWL ], [ 1, Moves.CONFUSION ], + [ 1, Moves.SYNCHRONOISE ], [ 1, Moves.TELEPORT ], [ 1, Moves.IMPRISON ], [ 1, Moves.PSYCHIC_TERRAIN ], @@ -10319,7 +10462,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 21, Moves.SCARY_FACE ], [ 24, Moves.CRUNCH ], [ 27, Moves.DRAGON_DANCE ], - [ 30, Moves.BREAKING_SWIPE ], + [ 30, Moves.DUAL_CHOP ], [ 33, Moves.FOCUS_ENERGY ], [ 36, Moves.DRAGON_PULSE ], [ 39, Moves.SWORDS_DANCE ], @@ -10332,6 +10475,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.BITE ], [ 1, Moves.FALSE_SWIPE ], + [ 1, Moves.DUAL_CHOP ], [ 9, Moves.ASSURANCE ], [ 12, Moves.TAUNT ], [ 15, Moves.SLASH ], @@ -10352,6 +10496,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.BITE ], [ 1, Moves.FALSE_SWIPE ], + [ 1, Moves.DUAL_CHOP ], [ 9, Moves.ASSURANCE ], [ 12, Moves.TAUNT ], [ 15, Moves.SLASH ], @@ -10393,6 +10538,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ENDURE ], [ 1, Moves.CHARM ], [ 1, Moves.AQUA_JET ], + [ 1, Moves.BIDE ], [ 9, Moves.ICY_WIND ], [ 12, Moves.PLAY_NICE ], [ 15, Moves.BRINE ], @@ -10473,6 +10619,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.WATER_GUN ], [ 1, Moves.THUNDER_SHOCK ], [ 1, Moves.MUD_SLAP ], + [ 1, Moves.MUD_SPORT ], [ 5, Moves.ENDURE ], [ 10, Moves.MUD_SHOT ], [ 15, Moves.REVENGE ], @@ -10609,6 +10756,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.BOUFFALANT]: [ [ 1, Moves.TACKLE ], [ 1, Moves.LEER ], + [ 1, Moves.PURSUIT ], [ 5, Moves.FOCUS_ENERGY ], [ 10, Moves.FURY_ATTACK ], [ 15, Moves.REVENGE ], @@ -11049,6 +11197,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 48, Moves.WOOD_HAMMER ], ], [Species.QUILLADIN]: [ + [ 0, Moves.NEEDLE_ARM ], [ 1, Moves.TACKLE ], [ 1, Moves.GROWL ], [ 1, Moves.VINE_WHIP ], @@ -11072,6 +11221,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ROLLOUT ], [ 1, Moves.HAMMER_ARM ], [ 1, Moves.FEINT ], + [ 1, Moves.NEEDLE_ARM ], [ 11, Moves.BITE ], [ 15, Moves.LEECH_SEED ], [ 19, Moves.PIN_MISSILE ], @@ -11178,6 +11328,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.WATER_GUN ], [ 1, Moves.QUICK_ATTACK ], [ 1, Moves.HAZE ], + [ 1, Moves.MAT_BLOCK ], [ 1, Moves.ROLE_PLAY ], [ 1, Moves.NIGHT_SLASH ], [ 10, Moves.LICK ], @@ -11213,6 +11364,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.MUD_SLAP ], [ 1, Moves.LASER_FOCUS ], + [ 1, Moves.ROTOTILLER ], [ 9, Moves.QUICK_ATTACK ], [ 12, Moves.MUD_SHOT ], [ 15, Moves.FLAIL ], @@ -11290,6 +11442,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.STUN_SPORE ], [ 1, Moves.SLEEP_POWDER ], [ 1, Moves.STRUGGLE_BUG ], + [ 1, Moves.POWDER ], [ 12, Moves.LIGHT_SCREEN ], [ 17, Moves.PSYBEAM ], [ 21, Moves.SUPERSONIC ], @@ -11372,6 +11525,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SAFEGUARD ], [ 1, Moves.SYNTHESIS ], [ 1, Moves.WISH ], + [ 1, Moves.LUCKY_CHANT ], [ 1, Moves.MAGICAL_LEAF ], [ 1, Moves.GRASS_KNOT ], [ 1, Moves.PETAL_BLIZZARD ], @@ -11533,6 +11687,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.AEGISLASH]: [ [ 0, Moves.KINGS_SHIELD ], [ 1, Moves.SWORDS_DANCE ], + [ 1, Moves.PURSUIT ], [ 1, Moves.TACKLE ], [ 1, Moves.SLASH ], [ 1, Moves.FURY_CUTTER ], @@ -11622,6 +11777,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.INKAY]: [ [ 1, Moves.TACKLE ], [ 1, Moves.PECK ], + [ 1, Moves.CONSTRICT ], [ 3, Moves.HYPNOSIS ], [ 6, Moves.WRAP ], [ 9, Moves.PAYBACK ], @@ -11640,6 +11796,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.WRAP ], [ 1, Moves.PECK ], + [ 1, Moves.CONSTRICT ], [ 1, Moves.HYPNOSIS ], [ 1, Moves.REVERSAL ], [ 9, Moves.PAYBACK ], @@ -11706,6 +11863,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.ACID ], [ 1, Moves.WATER_GUN ], [ 1, Moves.SMOKESCREEN ], + [ 1, Moves.FEINT_ATTACK ], [ 15, Moves.TAIL_WHIP ], [ 20, Moves.DOUBLE_TEAM ], [ 25, Moves.POISON_TAIL ], @@ -11766,6 +11924,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.HELIOLISK]: [ [ 1, Moves.POUND ], [ 1, Moves.TAIL_WHIP ], + [ 1, Moves.RAZOR_WIND ], [ 1, Moves.THUNDER_SHOCK ], [ 1, Moves.THUNDERBOLT ], [ 1, Moves.THUNDER_WAVE ], @@ -12161,6 +12320,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.YVELTAL]: [ [ 1, Moves.GUST ], [ 1, Moves.DOUBLE_TEAM ], + [ 1, Moves.RAZOR_WIND ], [ 5, Moves.TAUNT ], [ 10, Moves.SNARL ], [ 15, Moves.DISABLE ], @@ -12479,6 +12639,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TACKLE ], [ 1, Moves.LEER ], [ 1, Moves.PAYBACK ], + [ 1, Moves.PURSUIT ], [ 13, Moves.WORK_UP ], [ 19, Moves.BITE ], [ 23, Moves.MUD_SLAP ], @@ -12539,6 +12700,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 64, Moves.ZAP_CANNON ], ], [Species.CRABRAWLER]: [ + [ 1, Moves.BUBBLE ], + [ 1, Moves.VISE_GRIP ], [ 5, Moves.ROCK_SMASH ], [ 9, Moves.LEER ], [ 13, Moves.BUBBLE_BEAM ], @@ -12557,6 +12720,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.PROTECT ], [ 1, Moves.ROCK_SMASH ], + [ 1, Moves.BUBBLE ], + [ 1, Moves.PURSUIT ], [ 17, Moves.BUBBLE_BEAM ], [ 22, Moves.BRICK_BREAK ], [ 25, Moves.SLAM ], @@ -12725,6 +12890,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.DEWPIDER]: [ [ 1, Moves.WATER_GUN ], [ 1, Moves.INFESTATION ], + [ 1, Moves.WATER_SPORT ], [ 4, Moves.BUG_BITE ], [ 8, Moves.BITE ], [ 12, Moves.BUBBLE_BEAM ], @@ -12744,6 +12910,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.BUG_BITE ], [ 1, Moves.WIDE_GUARD ], [ 1, Moves.INFESTATION ], + [ 1, Moves.SPIDER_WEB ], [ 12, Moves.BUBBLE_BEAM ], [ 16, Moves.AQUA_RING ], [ 20, Moves.HEADBUTT ], @@ -12777,6 +12944,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.INGRAIN ], [ 1, Moves.NIGHT_SLASH ], [ 1, Moves.LEAFAGE ], + [ 1, Moves.DUAL_CHOP ], [ 15, Moves.RAZOR_LEAF ], [ 20, Moves.SWEET_SCENT ], [ 25, Moves.SLASH ], @@ -12806,6 +12974,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.CONFUSE_RAY ], [ 1, Moves.INGRAIN ], [ 1, Moves.ASTONISH ], + [ 1, Moves.FLASH ], [ 12, Moves.MEGA_DRAIN ], [ 16, Moves.SLEEP_POWDER ], [ 20, Moves.MOONLIGHT ], @@ -12844,6 +13013,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.TORMENT ], [ 1, Moves.KNOCK_OFF ], [ 1, Moves.ENDEAVOR ], + [ 1, Moves.CAPTIVATE ], [ 15, Moves.POISON_FANG ], [ 20, Moves.SWEET_SCENT ], [ 25, Moves.NASTY_PLOT ], @@ -12919,6 +13089,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.RAPID_SPIN ], [ 1, Moves.POWER_WHIP ], [ 1, Moves.PLAY_NICE ], + [ 1, Moves.PUNISHMENT ], [ 16, Moves.SWEET_SCENT ], [ 22, Moves.MAGICAL_LEAF ], [ 28, Moves.STOMP ], @@ -13037,6 +13208,9 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.PYUKUMUKU]: [ [ 1, Moves.HARDEN ], [ 1, Moves.BATON_PASS ], + [ 1, Moves.BIDE ], + [ 1, Moves.MUD_SPORT ], + [ 1, Moves.WATER_SPORT ], [ 5, Moves.HELPING_HAND ], [ 10, Moves.TAUNT ], [ 15, Moves.SAFEGUARD ], @@ -13238,10 +13412,12 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 44, Moves.OUTRAGE ], ], [Species.HAKAMO_O]: [ + [ 0, Moves.SKY_UPPERCUT ], [ 1, Moves.TACKLE ], [ 1, Moves.LEER ], [ 1, Moves.PROTECT ], [ 1, Moves.DRAGON_TAIL ], + [ 1, Moves.BIDE ], [ 12, Moves.SCARY_FACE ], [ 16, Moves.HEADBUTT ], [ 20, Moves.WORK_UP ], @@ -13259,6 +13435,8 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.LEER ], [ 1, Moves.PROTECT ], [ 1, Moves.DRAGON_TAIL ], + [ 1, Moves.BIDE ], + [ 1, Moves.SKY_UPPERCUT ], [ 12, Moves.SCARY_FACE ], [ 16, Moves.HEADBUTT ], [ 20, Moves.WORK_UP ], @@ -13363,6 +13541,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.METAL_CLAW ], [ 1, Moves.COSMIC_POWER ], [ 1, Moves.NOBLE_ROAR ], + [ 1, Moves.WAKE_UP_SLAP ], [ 7, Moves.IRON_HEAD ], [ 14, Moves.METAL_SOUND ], [ 21, Moves.ZEN_HEADBUTT ], @@ -13398,6 +13577,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.NIHILEGO]: [ [ 1, Moves.POUND ], [ 1, Moves.WRAP ], + [ 1, Moves.CONSTRICT ], [ 5, Moves.ACID ], [ 10, Moves.TICKLE ], [ 15, Moves.ACID_SPRAY ], @@ -13530,6 +13710,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.MOONLIGHT ], [ 1, Moves.GRAVITY ], [ 1, Moves.CHARGE_BEAM ], + [ 1, Moves.MIRROR_SHOT ], [ 8, Moves.STEALTH_ROCK ], [ 16, Moves.SLASH ], [ 24, Moves.NIGHT_SLASH ], @@ -13569,6 +13750,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.FEINT ], [ 1, Moves.COPYCAT ], [ 1, Moves.SHADOW_SNEAK ], + [ 1, Moves.PURSUIT ], [ 9, Moves.ROLE_PLAY ], [ 18, Moves.SHADOW_PUNCH ], [ 27, Moves.FORCE_PALM ], @@ -17333,6 +17515,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.METAL_BURST ], [ 1, Moves.IRON_HEAD ], [ 1, Moves.SNOWSCAPE ], + [ 1, Moves.ICE_BALL ], ], [Species.ALOLA_VULPIX]: [ [ 1, Moves.TAIL_WHIP ], @@ -17393,6 +17576,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.METAL_CLAW ], [ 1, Moves.ASTONISH ], [ 1, Moves.NIGHT_SLASH ], + [ 1, Moves.ROTOTILLER ], [ 12, Moves.MUD_SLAP ], [ 16, Moves.BULLDOZE ], [ 20, Moves.SUCKER_PUNCH ], @@ -17528,6 +17712,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_EXEGGUTOR]: [ [ 0, Moves.DRAGON_HAMMER ], + [ 1, Moves.BARRAGE ], [ 1, Moves.SEED_BOMB ], [ 1, Moves.PSYSHOCK ], [ 1, Moves.WOOD_HAMMER ], @@ -17549,6 +17734,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_MAROWAK]: [ [ 0, Moves.SHADOW_BONE ], + [ 1, Moves.BONE_CLUB ], [ 1, Moves.HEADBUTT ], [ 1, Moves.DOUBLE_EDGE ], [ 1, Moves.TAIL_WHIP ],