Merge branch 'main' of github.com:Greenlamp2/pokerogue into test_instance

This commit is contained in:
Greenlamp 2024-05-08 13:32:23 +02:00
commit d4c953c142
62 changed files with 10700 additions and 7644 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

View File

@ -146,14 +146,14 @@
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 3,
"h": 3
"w": 66,
"h": 55
},
"frame": {
"x": 132,
"y": 0,
"w": 3,
"h": 3
"x": 0,
"y": 112,
"w": 66,
"h": 55
}
},
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

View File

@ -0,0 +1,55 @@
import re
filenames = [['src/data/enums/moves.ts', 'move'], ['src/data/enums/abilities.ts', 'ability'], ['src/data/enums/species.ts', 'Pokémon']]
commentBlockStart = re.compile('\/\*[^\*].*') # Regex for the start of a comment block
commentBlockEnd = re.compile('.*,\*\/') # Regex for the end of a comment block
commentExp = re.compile('(?:\/\*\*.*\*\/)') # Regex for a url comment that already existed in the file
enumExp = re.compile('.*,') # Regex for a regular enum line
numberExp = re.compile(' +\= +\d+,')
replaceList = ['ALOLA', 'ETERNAL', 'GALAR', 'HISUI', 'PALDEA', 'BLOODMOON']
for args in filenames:
output = ''
skip = False # True when we should completely stop adding url comments for any reason
blockComment = False # True when currently reading a comment block
file = open(args[0], 'r')
line = file.readline()
while line:
if(skip): # Appends the next line in the file and moves on if we already hit the end of the enum
output += line
line = file.readline()
continue
skip = line.find('};') != -1 # True if we reached the end of an enum definition
# Determines when a comment block has started and we should stop adding url comments
if (commentBlockStart.findall(line)):
blockComment = True
if(not commentExp.findall(line)):
urlInsert = numberExp.sub('', line).strip().rstrip('\n').rstrip(',').title() # Clean up the enum line to only the enum
for replace in replaceList:
urlInsert = urlInsert.replace(replace.title() + '_', '')
if (not blockComment and enumExp.findall(line)):
output += ' /**{@link https://bulbapedia.bulbagarden.net/wiki/' + urlInsert + '_(' + args[1] + ') | Source} */\n'
output += line # Add the line to output since it isn't an existing url comment
# Determines if we're at the end of a comment block and can resume adding url comments
if (blockComment):
blockComment = not commentBlockEnd.findall(line)
line = file.readline()
file.close()
file = open(args[0], 'w', encoding='utf-8')
file.write(output,)
file.close

View File

@ -59,7 +59,7 @@ import { SceneBase } from './scene-base';
import CandyBar from './ui/candy-bar';
import { Variant, variantData } from './data/variant';
import { Localizable } from './plugins/i18n';
import { STARTING_WAVE_OVERRIDE, OPP_SPECIES_OVERRIDE, SEED_OVERRIDE, STARTING_BIOME_OVERRIDE } from './overrides';
import { STARTING_WAVE_OVERRIDE, OPP_SPECIES_OVERRIDE, SEED_OVERRIDE, STARTING_BIOME_OVERRIDE, DOUBLE_BATTLE_OVERRIDE } from './overrides';
import {InputsController} from "./inputs-controller";
import {UiInputs} from "./ui-inputs";
@ -842,6 +842,9 @@ export default class BattleScene extends SceneBase {
} else if (!battleConfig)
newDouble = !!double;
if (DOUBLE_BATTLE_OVERRIDE)
newDouble = true;
const lastBattle = this.currentBattle;
if (lastBattle?.double && !newDouble)

View File

@ -426,7 +426,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr {
}
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type) < 2) {
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, attacker) < 2) {
cancelled.value = true;
(args[0] as Utils.NumberHolder).value = 0;
return true;
@ -1794,7 +1794,7 @@ function getAnticipationCondition(): AbAttrCondition {
for (let opponent of pokemon.getOpponents()) {
for (let move of opponent.moveset) {
// move is super effective
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type) >= 2) {
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent) >= 2) {
return true;
}
// move is a OHKO
@ -1816,7 +1816,7 @@ function getAnticipationCondition(): AbAttrCondition {
Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC,
Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK][iv_val];
if (pokemon.getAttackTypeEffectiveness(type) >= 2) {
if (pokemon.getAttackTypeEffectiveness(type, opponent) >= 2) {
return true;
}
}
@ -1826,6 +1826,19 @@ function getAnticipationCondition(): AbAttrCondition {
};
}
/**
* Creates an ability condition that causes the ability to fail if that ability
* has already been used by that pokemon that battle. It requires an ability to
* be specified due to current limitations in how conditions on abilities work.
* @param {Abilities} ability The ability to check if it's already been applied
* @returns {AbAttrCondition} The condition
*/
function getOncePerBattleCondition(ability: Abilities): AbAttrCondition {
return (pokemon: Pokemon) => {
return !pokemon.battleData?.abilitiesApplied.includes(ability);
}
}
export class ForewarnAbAttr extends PostSummonAbAttr {
constructor() {
super(true);
@ -2472,6 +2485,25 @@ export class NoFusionAbilityAbAttr extends AbAttr {
}
}
export class IgnoreTypeImmunityAbAttr extends AbAttr {
defenderType: Type;
allowedMoveTypes: Type[];
constructor(defenderType: Type, allowedMoveTypes: Type[]) {
super(true);
this.defenderType = defenderType;
this.allowedMoveTypes = allowedMoveTypes;
}
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (this.defenderType === (args[1] as Type) && this.allowedMoveTypes.includes(args[0] as Type)) {
cancelled.value = true;
return true;
}
return false;
}
}
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr },
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
return new Promise(resolve => {
@ -2503,6 +2535,9 @@ function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any
return applyNextAbAttr();
pokemon.scene.setPhaseQueueSplice();
const onApplySuccess = () => {
if (pokemon.battleData && !pokemon.battleData.abilitiesApplied.includes(ability.id)) {
pokemon.battleData.abilitiesApplied.push(ability.id);
}
if (attr.showAbility && !quiet) {
if (showAbilityInstant)
pokemon.scene.abilityBar.showAbility(pokemon, passive);
@ -2973,15 +3008,15 @@ export function initAbilities() {
.attr(IgnoreOpponentStatChangesAbAttr)
.ignorable(),
new Ability(Abilities.TINTED_LENS, 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) <= 0.5, 2),
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) <= 0.5, 2),
new Ability(Abilities.FILTER, 4)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 0.75)
.ignorable(),
new Ability(Abilities.SLOW_START, 4)
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5),
new Ability(Abilities.SCRAPPY, 4)
.attr(IntimidateImmunityAbAttr)
.partial(),
new Ability(Abilities.SCRAPPY, 4)
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
.attr(IntimidateImmunityAbAttr),
new Ability(Abilities.STORM_DRAIN, 4)
.attr(RedirectTypeMoveAbAttr, Type.WATER)
.attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1)
@ -2990,7 +3025,7 @@ export function initAbilities() {
.attr(BlockWeatherDamageAttr, WeatherType.HAIL)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW),
new Ability(Abilities.SOLID_ROCK, 4)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 0.75)
.ignorable(),
new Ability(Abilities.SNOW_WARNING, 4)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SNOW)
@ -3000,7 +3035,7 @@ export function initAbilities() {
new Ability(Abilities.FRISK, 4)
.attr(FriskAbAttr),
new Ability(Abilities.RECKLESS, 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => move.getAttrs(RecoilAttr).length && move.id !== Moves.STRUGGLE, 1.2),
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.RECKLESS_MOVE), 1.2),
new Ability(Abilities.MULTITYPE, 4)
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
@ -3258,7 +3293,7 @@ export function initAbilities() {
.attr(UnsuppressableAbilityAbAttr)
.attr(NoFusionAbilityAbAttr),
new Ability(Abilities.DISGUISE, 7)
.attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex == 0 && target.getAttackTypeEffectiveness(move.type) > 0)
.attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex == 0 && target.getAttackTypeEffectiveness(move.type, user) > 0)
.attr(PostSummonFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1)
.attr(PostBattleInitFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1)
.attr(PostDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1)
@ -3356,13 +3391,15 @@ export function initAbilities() {
new Ability(Abilities.SHADOW_SHIELD, 7)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getHpRatio() === 1, 0.5),
new Ability(Abilities.PRISM_ARMOR, 7)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75),
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 0.75),
new Ability(Abilities.NEUROFORCE, 7)
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 1.25),
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2, 1.25),
new Ability(Abilities.INTREPID_SWORD, 8)
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, 1, true),
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, 1, true)
.condition(getOncePerBattleCondition(Abilities.INTREPID_SWORD)),
new Ability(Abilities.DAUNTLESS_SHIELD, 8)
.attr(PostSummonStatChangeAbAttr, BattleStat.DEF, 1, true),
.attr(PostSummonStatChangeAbAttr, BattleStat.DEF, 1, true)
.condition(getOncePerBattleCondition(Abilities.DAUNTLESS_SHIELD)),
new Ability(Abilities.LIBERO, 8)
.unimplemented(),
new Ability(Abilities.BALL_FETCH, 8)
@ -3434,7 +3471,8 @@ export function initAbilities() {
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr)
.attr(NoFusionAbilityAbAttr),
.attr(NoFusionAbilityAbAttr)
.condition((pokemon) => !pokemon.isTerastallized()),
new Ability(Abilities.QUICK_DRAW, 8)
.unimplemented(),
new Ability(Abilities.UNSEEN_FIST, 8)
@ -3511,13 +3549,15 @@ export function initAbilities() {
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.PROTOSYNTHESIS, 0, WeatherType.SUNNY, WeatherType.HARSH_SUN)
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr),
.attr(NoTransformAbilityAbAttr)
.partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages
new Ability(Abilities.QUARK_DRIVE, 9)
.conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), PostSummonAddBattlerTagAbAttr, BattlerTagType.QUARK_DRIVE, 0, true)
.attr(PostTerrainChangeAddBattlerTagAttr, BattlerTagType.QUARK_DRIVE, 0, TerrainType.ELECTRIC)
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr),
.attr(NoTransformAbilityAbAttr)
.partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages
new Ability(Abilities.GOOD_AS_GOLD, 9)
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().category === MoveCategory.STATUS)
.ignorable()
@ -3565,10 +3605,12 @@ export function initAbilities() {
.attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS)
.partial(),
new Ability(Abilities.MINDS_EYE, 9)
.ignorable()
.unimplemented(),
.attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
.ignorable() // TODO: evasiveness bypass should not be ignored, but accuracy immunity should
.partial(),
new Ability(Abilities.SUPERSWEET_SYRUP, 9)
.unimplemented(),
.attr(PostSummonStatChangeAbAttr, BattleStat.EVA, -1)
.condition(getOncePerBattleCondition(Abilities.SUPERSWEET_SYRUP)),
new Ability(Abilities.HOSPITALITY, 9)
.attr(PostSummonAllyHealAbAttr, 4, true),
new Ability(Abilities.TOXIC_CHAIN, 9)

View File

@ -920,7 +920,7 @@ export class HighestStatBoostTag extends AbilityBattlerTag {
stats.map(s => pokemon.getBattleStat(s)).reduce((highestValue: integer, value: integer, i: integer) => {
if (value > highestValue) {
highestStat = stats[i];
return highestValue += value;
return value;
}
return highestValue;
}, 0);

View File

@ -114,7 +114,8 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status.effect)));
pokemon.resetStatus();
pokemon.updateInfo();
} else if (pokemon.getTag(BattlerTagType.CONFUSED))
}
if (pokemon.getTag(BattlerTagType.CONFUSED))
pokemon.lapseTag(BattlerTagType.CONFUSED);
};
case BerryType.LIECHI:

View File

@ -1639,7 +1639,8 @@ export const trainerTypeDialogue = {
},
[TrainerType.HAU]: {
encounter: [
`I wonder if a Trainer battles differently depending on whether they're from a warm region or a cold region. Let's test it out!`,
`I wonder if a Trainer battles differently depending on whether they're from a warm region or a cold region.
$Let's test it out!`,
],
victory: [
`That was awesome! I think I kinda understand your vibe a little better now!`,

View File

@ -5,18 +5,18 @@ import * as Utils from "../utils";
export const speciesEggMoves = {
[Species.BULBASAUR]: [ Moves.STRENGTH_SAP, Moves.SLUDGE_BOMB, Moves.EARTH_POWER, Moves.SAPPY_SEED ],
[Species.BULBASAUR]: [ Moves.GIGA_DRAIN, Moves.SLUDGE_BOMB, Moves.EARTH_POWER, Moves.SAPPY_SEED ],
[Species.CHARMANDER]: [ Moves.DRAGON_DANCE, Moves.BITTER_BLADE, Moves.EARTH_POWER, Moves.OBLIVION_WING ],
[Species.SQUIRTLE]: [ Moves.ICE_BEAM, Moves.DARK_PULSE, Moves.BOUNCY_BUBBLE, Moves.ORIGIN_PULSE ],
[Species.CATERPIE]: [ Moves.EARTH_POWER, Moves.SILK_TRAP, Moves.STICKY_WEB, Moves.BLEAKWIND_STORM ],
[Species.WEEDLE]: [ Moves.DRILL_RUN, Moves.SWORDS_DANCE, Moves.BANEFUL_BUNKER, Moves.BARB_BARRAGE ],
[Species.PIDGEY]: [ Moves.HEAT_WAVE, Moves.FOCUS_BLAST, Moves.U_TURN, Moves.WILDBOLT_STORM ],
[Species.RATTATA]: [ Moves.HYPER_FANG, Moves.PSYCHIC_FANGS, Moves.FIRE_FANG, Moves.EXTREME_SPEED ],
[Species.SPEAROW]: [ Moves.DUAL_WINGBEAT, Moves.SUCKER_PUNCH, Moves.PARTING_SHOT, Moves.HYPER_DRILL ],
[Species.SPEAROW]: [ Moves.FLOATY_FALL, Moves.EXTREME_SPEED, Moves.TIDY_UP, Moves.TRIPLE_ARROWS ],
[Species.EKANS]: [ Moves.SHED_TAIL, Moves.DRAGON_DANCE, Moves.SLACK_OFF, Moves.NOXIOUS_TORQUE ],
[Species.SANDSHREW]: [ Moves.DIRE_CLAW, Moves.CEASELESS_EDGE, Moves.SHORE_UP, Moves.PRECIPICE_BLADES ],
[Species.NIDORAN_F]: [ Moves.SCALD, Moves.SHORE_UP, Moves.CALM_MIND, Moves.BANEFUL_BUNKER ],
[Species.NIDORAN_M]: [ Moves.DARK_PULSE, Moves.SHORE_UP, Moves.CALM_MIND, Moves.KINGS_SHIELD ],
[Species.NIDORAN_F]: [ Moves.DIRE_CLAW, Moves.SHORE_UP, Moves.THOUSAND_WAVES, Moves.SALT_CURE ],
[Species.NIDORAN_M]: [ Moves.NOXIOUS_TORQUE, Moves.KINGS_SHIELD, Moves.NO_RETREAT, Moves.PRECIPICE_BLADES ],
[Species.VULPIX]: [ Moves.MOONBLAST, Moves.PSYCHIC, Moves.MORNING_SUN, Moves.TAIL_GLOW ],
[Species.ZUBAT]: [ Moves.FLOATY_FALL, Moves.DIRE_CLAW, Moves.SWORDS_DANCE, Moves.BRAVE_BIRD ],
[Species.ODDISH]: [ Moves.SLUDGE_BOMB, Moves.FIERY_DANCE, Moves.STRENGTH_SAP, Moves.SPORE ],
@ -28,24 +28,24 @@ export const speciesEggMoves = {
[Species.MANKEY]: [ Moves.DRAIN_PUNCH, Moves.RAGING_FURY, Moves.METEOR_MASH, Moves.NO_RETREAT ],
[Species.GROWLITHE]: [ Moves.ZING_ZAP, Moves.PARTING_SHOT, Moves.MORNING_SUN, Moves.SACRED_FIRE ],
[Species.POLIWAG]: [ Moves.BOUNCY_BUBBLE, Moves.WILDBOLT_STORM, Moves.DRAIN_PUNCH, Moves.SURGING_STRIKES ],
[Species.ABRA]: [ Moves.MOONBLAST, Moves.EARTH_POWER, Moves.THUNDERBOLT, Moves.LUSTER_PURGE ],
[Species.MACHOP]: [ Moves.MACH_PUNCH, Moves.METEOR_MASH, Moves.FLYING_PRESS, Moves.FISSURE ],
[Species.BELLSPROUT]: [ Moves.SOLAR_BLADE, Moves.WEATHER_BALL, Moves.FIRE_LASH, Moves.STRENGTH_SAP ],
[Species.ABRA]: [ Moves.MOONBLAST, Moves.FLAMETHROWER, Moves.THUNDERBOLT, Moves.PSYSTRIKE ],
[Species.MACHOP]: [ Moves.MACH_PUNCH, Moves.METEOR_MASH, Moves.ICE_HAMMER, Moves.FISSURE ],
[Species.BELLSPROUT]: [ Moves.SOLAR_BLADE, Moves.STRENGTH_SAP, Moves.FIRE_LASH, Moves.VICTORY_DANCE ],
[Species.TENTACOOL]: [ Moves.BANEFUL_BUNKER, Moves.STRENGTH_SAP, Moves.HAZE, Moves.MALIGNANT_CHAIN ],
[Species.GEODUDE]: [ Moves.BODY_PRESS, Moves.BULK_UP, Moves.SHORE_UP, Moves.HEAD_SMASH ],
[Species.PONYTA]: [ Moves.HIGH_HORSEPOWER, Moves.FIRE_LASH, Moves.MORNING_SUN, Moves.VOLT_TACKLE ],
[Species.PONYTA]: [ Moves.HIGH_HORSEPOWER, Moves.FIRE_LASH, Moves.SWORDS_DANCE, Moves.VOLT_TACKLE ],
[Species.SLOWPOKE]: [ Moves.BOUNCY_BUBBLE, Moves.PARTING_SHOT, Moves.COSMIC_POWER, Moves.LUMINA_CRASH ],
[Species.MAGNEMITE]: [ Moves.RECOVER, Moves.BODY_PRESS, Moves.ICE_BEAM, Moves.THUNDERCLAP ],
[Species.MAGNEMITE]: [ Moves.PARABOLIC_CHARGE, Moves.BODY_PRESS, Moves.ICE_BEAM, Moves.THUNDERCLAP ],
[Species.FARFETCHD]: [ Moves.BATON_PASS, Moves.SACRED_SWORD, Moves.ROOST, Moves.VICTORY_DANCE ],
[Species.DODUO]: [ Moves.TRIPLE_AXEL, Moves.HEAD_CHARGE, Moves.BRAVE_BIRD, Moves.TRIPLE_ARROWS ],
[Species.DODUO]: [ Moves.TRIPLE_AXEL, Moves.MULTI_ATTACK, Moves.FLOATY_FALL, Moves.TRIPLE_ARROWS ],
[Species.SEEL]: [ Moves.FREEZE_DRY, Moves.CHILLY_RECEPTION, Moves.SLACK_OFF, Moves.BOUNCY_BUBBLE ],
[Species.GRIMER]: [ Moves.SHADOW_SNEAK, Moves.CURSE, Moves.STRENGTH_SAP, Moves.NOXIOUS_TORQUE ],
[Species.SHELLDER]: [ Moves.BODY_PRESS, Moves.WATER_SHURIKEN, Moves.BANEFUL_BUNKER, Moves.RECOVER ],
[Species.SHELLDER]: [ Moves.ROCK_BLAST, Moves.WATER_SHURIKEN, Moves.BANEFUL_BUNKER, Moves.BONE_RUSH ],
[Species.GASTLY]: [ Moves.FROST_BREATH, Moves.AURA_SPHERE, Moves.NASTY_PLOT, Moves.MALIGNANT_CHAIN ],
[Species.ONIX]: [ Moves.SHORE_UP, Moves.BODY_PRESS, Moves.HEAD_SMASH, Moves.SPIN_OUT ],
[Species.DROWZEE]: [ Moves.DREAM_EATER, Moves.RECOVER, Moves.NIGHTMARE, Moves.SPORE ],
[Species.KRABBY]: [ Moves.MOUNTAIN_GALE, Moves.LIQUIDATION, Moves.SHORE_UP, Moves.SHELL_SMASH ],
[Species.VOLTORB]: [ Moves.BUZZY_BUZZ, Moves.VOLT_SWITCH, Moves.ENERGY_BALL, Moves.NASTY_PLOT ],
[Species.KRABBY]: [ Moves.ICICLE_CRASH, Moves.LIQUIDATION, Moves.IVY_CUDGEL, Moves.SHELL_SMASH ],
[Species.VOLTORB]: [ Moves.BUZZY_BUZZ, Moves.OVERHEAT, Moves.FROST_BREATH, Moves.TAIL_GLOW ],
[Species.EXEGGCUTE]: [ Moves.MYSTICAL_POWER, Moves.APPLE_ACID, Moves.TRICK_ROOM, Moves.FICKLE_BEAM ],
[Species.CUBONE]: [ Moves.HEAD_SMASH, Moves.WOOD_HAMMER, Moves.PAIN_SPLIT, Moves.VOLT_TACKLE ],
[Species.LICKITUNG]: [ Moves.BODY_SLAM, Moves.FIRE_LASH, Moves.GRAV_APPLE, Moves.MILK_DRINK ],
@ -53,7 +53,7 @@ export const speciesEggMoves = {
[Species.RHYHORN]: [ Moves.SHORE_UP, Moves.WAVE_CRASH, Moves.FLARE_BLITZ, Moves.HEAD_SMASH ],
[Species.TANGELA]: [ Moves.STRENGTH_SAP, Moves.INFESTATION, Moves.PARTING_SHOT, Moves.SAPPY_SEED ],
[Species.KANGASKHAN]: [ Moves.POWER_UP_PUNCH, Moves.BREAKING_SWIPE, Moves.RETURN, Moves.SEISMIC_TOSS ],
[Species.HORSEA]: [ Moves.SNIPE_SHOT, Moves.NASTY_PLOT, Moves.HURRICANE, Moves.SPACIAL_REND ],
[Species.HORSEA]: [ Moves.SNIPE_SHOT, Moves.FROST_BREATH, Moves.HURRICANE, Moves.DRAGON_ENERGY ],
[Species.GOLDEEN]: [ Moves.DRILL_RUN, Moves.FLIP_TURN, Moves.DRAGON_DANCE, Moves.FISHIOUS_REND ],
[Species.STARYU]: [ Moves.CALM_MIND, Moves.BOUNCY_BUBBLE, Moves.MOONBLAST, Moves.MYSTICAL_POWER ],
[Species.SCYTHER]: [ Moves.GEAR_GRIND, Moves.BUG_BITE, Moves.STORM_THROW, Moves.MIGHTY_CLEAVE ],
@ -64,11 +64,11 @@ export const speciesEggMoves = {
[Species.DITTO]: [ Moves.MIMIC, Moves.COPYCAT, Moves.ME_FIRST, Moves.METRONOME ],
[Species.EEVEE]: [ Moves.WISH, Moves.REVELATION_DANCE, Moves.TRI_ATTACK, Moves.NO_RETREAT ],
[Species.PORYGON]: [ Moves.BUZZY_BUZZ, Moves.AURA_SPHERE, Moves.TOPSY_TURVY, Moves.TECHNO_BLAST ],
[Species.OMANYTE]: [ Moves.SCALD, Moves.EARTH_POWER, Moves.POWER_GEM, Moves.STRENGTH_SAP ],
[Species.OMANYTE]: [ Moves.FREEZE_DRY, Moves.EARTH_POWER, Moves.POWER_GEM, Moves.STEAM_ERUPTION ],
[Species.KABUTO]: [ Moves.CEASELESS_EDGE, Moves.DRILL_RUN, Moves.AQUA_CUTTER, Moves.MIGHTY_CLEAVE ],
[Species.AERODACTYL]: [ Moves.FLOATY_FALL, Moves.HEAD_SMASH, Moves.SWORDS_DANCE, Moves.MIGHTY_CLEAVE ],
[Species.ARTICUNO]: [ Moves.AURA_SPHERE, Moves.CALM_MIND, Moves.AURORA_VEIL, Moves.AEROBLAST ],
[Species.ZAPDOS]: [ Moves.WEATHER_BALL, Moves.CALM_MIND, Moves.SPIKY_SHIELD, Moves.ELECTRO_SHOT ],
[Species.ZAPDOS]: [ Moves.WEATHER_BALL, Moves.CALM_MIND, Moves.SANDSEAR_STORM, Moves.ELECTRO_SHOT ],
[Species.MOLTRES]: [ Moves.SCORCHING_SANDS, Moves.CALM_MIND, Moves.BURNING_BULWARK, Moves.TORCH_SONG ],
[Species.DRATINI]: [ Moves.DRAGON_HAMMER, Moves.METEOR_MASH, Moves.FIRE_LASH, Moves.FLOATY_FALL ],
[Species.MEWTWO]: [ Moves.METEOR_MASH, Moves.MOONBLAST, Moves.PLASMA_FISTS, Moves.PHOTON_GEYSER ],
@ -86,7 +86,7 @@ export const speciesEggMoves = {
[Species.IGGLYBUFF]: [ Moves.MOONBLAST, Moves.APPLE_ACID, Moves.WISH, Moves.BOOMBURST ],
[Species.TOGEPI]: [ Moves.SCORCHING_SANDS, Moves.ROOST, Moves.MOONBLAST, Moves.FIERY_DANCE ],
[Species.NATU]: [ Moves.AEROBLAST, Moves.ROOST, Moves.CALM_MIND, Moves.LUMINA_CRASH ],
[Species.MAREEP]: [ Moves.ICE_BEAM, Moves.MILK_DRINK, Moves.DRAGON_ENERGY, Moves.TAIL_GLOW ],
[Species.MAREEP]: [ Moves.ICE_BEAM, Moves.PARABOLIC_CHARGE, Moves.DRAGON_ENERGY, Moves.TAIL_GLOW ],
[Species.HOPPIP]: [ Moves.AIR_SLASH, Moves.STRENGTH_SAP, Moves.QUIVER_DANCE, Moves.SEED_FLARE ],
[Species.AIPOM]: [ Moves.TIDY_UP, Moves.STORM_THROW, Moves.FAKE_OUT, Moves.POPULATION_BOMB ],
[Species.SUNKERN]: [ Moves.SPORE, Moves.SAPPY_SEED, Moves.FIERY_DANCE, Moves.HYDRO_STEAM ],
@ -124,31 +124,31 @@ export const speciesEggMoves = {
[Species.ENTEI]: [ Moves.BURNING_BULWARK, Moves.DRAGON_DANCE, Moves.EARTHQUAKE, Moves.MIGHTY_CLEAVE ],
[Species.SUICUNE]: [ Moves.HYDRO_STEAM, Moves.CALM_MIND, Moves.FREEZE_DRY, Moves.BOUNCY_BUBBLE ],
[Species.LARVITAR]: [ Moves.DRAGON_DANCE, Moves.MOUNTAIN_GALE, Moves.MIGHTY_CLEAVE, Moves.SHORE_UP ],
[Species.LUGIA]: [ Moves.COSMIC_POWER, Moves.STORED_POWER, Moves.SCALD, Moves.OBLIVION_WING ],
[Species.LUGIA]: [ Moves.TAKE_HEART, Moves.STORED_POWER, Moves.SCALD, Moves.OBLIVION_WING ],
[Species.HO_OH]: [ Moves.BURNING_BULWARK, Moves.U_TURN, Moves.BRAVE_BIRD, Moves.REVIVAL_BLESSING ],
[Species.CELEBI]: [ Moves.MYSTICAL_POWER, Moves.STORED_POWER, Moves.COSMIC_POWER, Moves.SEED_FLARE ],
[Species.TREECKO]: [ Moves.DRAGON_PULSE, Moves.DRAGON_ENERGY, Moves.SECRET_SWORD, Moves.SEED_FLARE ],
[Species.TORCHIC]: [ Moves.THUNDEROUS_KICK, Moves.POWER_UP_PUNCH, Moves.KNOCK_OFF, Moves.SACRED_FIRE ],
[Species.MUDKIP]: [ Moves.SHORE_UP, Moves.ICICLE_CRASH, Moves.BULK_UP, Moves.WAVE_CRASH ],
[Species.TORCHIC]: [ Moves.HIGH_JUMP_KICK, Moves.SUPERCELL_SLAM, Moves.KNOCK_OFF, Moves.V_CREATE ],
[Species.MUDKIP]: [ Moves.SHORE_UP, Moves.ICICLE_CRASH, Moves.BULK_UP, Moves.SURGING_STRIKES ],
[Species.POOCHYENA]: [ Moves.JAW_LOCK, Moves.PSYCHIC_FANGS, Moves.POISON_FANG, Moves.NO_RETREAT ],
[Species.ZIGZAGOON]: [ Moves.EXTREME_SPEED, Moves.ENDURE, Moves.HIGH_HORSEPOWER, Moves.TIDY_UP ],
[Species.WURMPLE]: [ Moves.BATON_PASS, Moves.BLEAKWIND_STORM, Moves.STICKY_WEB, Moves.MALIGNANT_CHAIN ],
[Species.LOTAD]: [ Moves.REVELATION_DANCE, Moves.APPLE_ACID, Moves.ICE_BEAM, Moves.QUIVER_DANCE ],
[Species.SEEDOT]: [ Moves.SWORDS_DANCE, Moves.GRASSY_GLIDE, Moves.KOWTOW_CLEAVE, Moves.IVY_CUDGEL ],
[Species.TAILLOW]: [ Moves.BOOMBURST, Moves.FACADE, Moves.DRILL_RUN, Moves.VOLT_TACKLE ],
[Species.TAILLOW]: [ Moves.SWORDS_DANCE, Moves.FACADE, Moves.DRILL_RUN, Moves.EXTREME_SPEED ],
[Species.WINGULL]: [ Moves.THUNDER, Moves.FLIP_TURN, Moves.DEFOG, Moves.STEAM_ERUPTION ],
[Species.RALTS]: [ Moves.BOOMBURST, Moves.BITTER_BLADE, Moves.PSYBLADE, Moves.VICTORY_DANCE ],
[Species.RALTS]: [ Moves.BOOMBURST, Moves.BITTER_BLADE, Moves.QUIVER_DANCE, Moves.VICTORY_DANCE ],
[Species.SURSKIT]: [ Moves.ROOST, Moves.FIERY_DANCE, Moves.STICKY_WEB, Moves.BLEAKWIND_STORM ],
[Species.SHROOMISH]: [ Moves.ACCELEROCK, Moves.TRAILBLAZE, Moves.STORM_THROW, Moves.SAPPY_SEED ],
[Species.SLAKOTH]: [ Moves.FACADE, Moves.JUMP_KICK, Moves.KNOCK_OFF, Moves.SKILL_SWAP ],
[Species.NINCADA]: [ Moves.ATTACK_ORDER, Moves.STICKY_WEB, Moves.POLTERGEIST, Moves.SHELL_SMASH ],
[Species.WHISMUR]: [ Moves.ALLURING_VOICE, Moves.SLACK_OFF, Moves.SPARKLING_ARIA, Moves.TORCH_SONG ],
[Species.NINCADA]: [ Moves.ATTACK_ORDER, Moves.STICKY_WEB, Moves.SPIRIT_SHACKLE, Moves.SHELL_SMASH ],
[Species.WHISMUR]: [ Moves.ALLURING_VOICE, Moves.TRICK_ROOM, Moves.SPARKLING_ARIA, Moves.TORCH_SONG ],
[Species.MAKUHITA]: [ Moves.STORM_THROW, Moves.SLACK_OFF, Moves.HEAT_CRASH, Moves.DOUBLE_IRON_BASH ],
[Species.AZURILL]: [ Moves.SLACK_OFF, Moves.SPIRIT_BREAK, Moves.TIDY_UP, Moves.WAVE_CRASH ],
[Species.AZURILL]: [ Moves.JET_PUNCH, Moves.SPIRIT_BREAK, Moves.SWORDS_DANCE, Moves.SURGING_STRIKES ],
[Species.NOSEPASS]: [ Moves.SHORE_UP, Moves.BODY_PRESS, Moves.CALM_MIND, Moves.TACHYON_CUTTER ],
[Species.SKITTY]: [ Moves.THUNDEROUS_KICK, Moves.SKETCH, Moves.TIDY_UP, Moves.V_CREATE ],
[Species.SABLEYE]: [ Moves.RECOVER, Moves.TOPSY_TURVY, Moves.PARTING_SHOT, Moves.SALT_CURE ],
[Species.MAWILE]: [ Moves.BULLET_PUNCH, Moves.RECOVER, Moves.EARTHQUAKE, Moves.DOUBLE_IRON_BASH ],
[Species.MAWILE]: [ Moves.BULLET_PUNCH, Moves.MAGICAL_TORQUE, Moves.EARTHQUAKE, Moves.DOUBLE_IRON_BASH ],
[Species.ARON]: [ Moves.HEAD_SMASH, Moves.BODY_PRESS, Moves.SHORE_UP, Moves.SALT_CURE ],
[Species.MEDITITE]: [ Moves.THUNDEROUS_KICK, Moves.SUCKER_PUNCH, Moves.BULLET_PUNCH, Moves.PHOTON_GEYSER ],
[Species.ELECTRIKE]: [ Moves.RISING_VOLTAGE, Moves.FLAMETHROWER, Moves.NASTY_PLOT, Moves.ICE_BEAM ],
@ -162,40 +162,40 @@ export const speciesEggMoves = {
[Species.NUMEL]: [ Moves.SANDSEAR_STORM, Moves.SPIKES, Moves.SHORE_UP, Moves.SEARING_SHOT ],
[Species.TORKOAL]: [ Moves.SLACK_OFF, Moves.SPIKES, Moves.BODY_PRESS, Moves.BURNING_BULWARK ],
[Species.SPOINK]: [ Moves.AURA_SPHERE, Moves.MILK_DRINK, Moves.COSMIC_POWER, Moves.EXPANDING_FORCE ],
[Species.SPINDA]: [ Moves.SUPERPOWER, Moves.RECOVER, Moves.FLEUR_CANNON, Moves.V_CREATE ],
[Species.SPINDA]: [ Moves.SUPERPOWER, Moves.SLACK_OFF, Moves.FLEUR_CANNON, Moves.V_CREATE ],
[Species.TRAPINCH]: [ Moves.FIRE_LASH, Moves.DRAGON_DARTS, Moves.THOUSAND_ARROWS, Moves.DRAGON_ENERGY ],
[Species.CACNEA]: [ Moves.SCORCHING_SANDS, Moves.CEASELESS_EDGE, Moves.NIGHT_DAZE, Moves.SAPPY_SEED ],
[Species.CACNEA]: [ Moves.EARTH_POWER, Moves.CEASELESS_EDGE, Moves.NIGHT_DAZE, Moves.IVY_CUDGEL ],
[Species.SWABLU]: [ Moves.ROOST, Moves.NASTY_PLOT, Moves.FLOATY_FALL, Moves.BOOMBURST ],
[Species.ZANGOOSE]: [ Moves.FACADE, Moves.HIGH_HORSEPOWER, Moves.EXTREME_SPEED, Moves.TIDY_UP ],
[Species.SEVIPER]: [ Moves.DIRE_CLAW, Moves.NASTY_PLOT, Moves.SUCKER_PUNCH, Moves.SHED_TAIL ],
[Species.LUNATONE]: [ Moves.POWER_GEM, Moves.NIGHT_DAZE, Moves.STORED_POWER, Moves.LUMINA_CRASH ],
[Species.SOLROCK]: [ Moves.PSYSHIELD_BASH, Moves.MIGHTY_CLEAVE, Moves.POWER_TRIP, Moves.SACRED_FIRE ],
[Species.BARBOACH]: [ Moves.DRAGON_DANCE, Moves.SUPERCELL_SLAM, Moves.ICE_SPINNER, Moves.WAVE_CRASH ],
[Species.CORPHISH]: [ Moves.CEASELESS_EDGE, Moves.AQUA_JET, Moves.WAVE_CRASH, Moves.SHELL_SMASH ],
[Species.CORPHISH]: [ Moves.CEASELESS_EDGE, Moves.JET_PUNCH, Moves.WAVE_CRASH, Moves.SHELL_SMASH ],
[Species.BALTOY]: [ Moves.RECOVER, Moves.STORED_POWER, Moves.BODY_PRESS, Moves.MYSTICAL_POWER ],
[Species.LILEEP]: [ Moves.METEOR_BEAM, Moves.SCALD, Moves.STEALTH_ROCK, Moves.SAPPY_SEED ],
[Species.LILEEP]: [ Moves.POWER_GEM, Moves.SCALD, Moves.STONE_AXE, Moves.SAPPY_SEED ],
[Species.ANORITH]: [ Moves.LIQUIDATION, Moves.LEECH_LIFE, Moves.DRAGON_DANCE, Moves.MIGHTY_CLEAVE ],
[Species.FEEBAS]: [ Moves.CALM_MIND, Moves.FREEZE_DRY, Moves.MOONBLAST, Moves.STEAM_ERUPTION ],
[Species.CASTFORM]: [ Moves.BOOMBURST, Moves.HYDRO_STEAM, Moves.CLEAR_SMOG, Moves.QUIVER_DANCE ],
[Species.KECLEON]: [ Moves.DRAIN_PUNCH, Moves.DRAGON_DANCE, Moves.EXTREME_SPEED, Moves.MULTI_ATTACK ],
[Species.SHUPPET]: [ Moves.DRAIN_PUNCH, Moves.RECOVER, Moves.PARTING_SHOT, Moves.SPECTRAL_THIEF ],
[Species.DUSKULL]: [ Moves.BULK_UP, Moves.DRAIN_PUNCH, Moves.RECOVER, Moves.RAGE_FIST ],
[Species.SHUPPET]: [ Moves.DRAIN_PUNCH, Moves.TOPSY_TURVY, Moves.PARTING_SHOT, Moves.SPECTRAL_THIEF ],
[Species.DUSKULL]: [ Moves.BULK_UP, Moves.DRAIN_PUNCH, Moves.STRENGTH_SAP, Moves.RAGE_FIST ],
[Species.TROPIUS]: [ Moves.STUFF_CHEEKS, Moves.EARTH_POWER, Moves.APPLE_ACID, Moves.SAPPY_SEED ],
[Species.ABSOL]: [ Moves.KOWTOW_CLEAVE, Moves.SACRED_SWORD, Moves.DIRE_CLAW, Moves.BITTER_BLADE ],
[Species.WYNAUT]: [ Moves.RECOVER, Moves.COSMIC_POWER, Moves.TAUNT, Moves.SHED_TAIL ],
[Species.SNORUNT]: [ Moves.AURORA_VEIL, Moves.HEAD_CHARGE, Moves.POLTERGEIST, Moves.FREEZY_FROST ],
[Species.WYNAUT]: [ Moves.RECOVER, Moves.PERISH_SONG, Moves.TAUNT, Moves.SHED_TAIL ],
[Species.SNORUNT]: [ Moves.AURORA_VEIL, Moves.HYPER_VOICE, Moves.EARTH_POWER, Moves.NO_RETREAT ],
[Species.SPHEAL]: [ Moves.FLIP_TURN, Moves.FREEZE_DRY, Moves.SLACK_OFF, Moves.STEAM_ERUPTION ],
[Species.CLAMPERL]: [ Moves.ICE_SPINNER, Moves.LIQUIDATION, Moves.EARTH_POWER, Moves.ORIGIN_PULSE ],
[Species.RELICANTH]: [ Moves.BODY_PRESS, Moves.SHORE_UP, Moves.WAVE_CRASH, Moves.FISHIOUS_REND ],
[Species.LUVDISC]: [ Moves.BATON_PASS, Moves.THIEF, Moves.BOUNCY_BUBBLE, Moves.TAKE_HEART ],
[Species.BAGON]: [ Moves.IRON_HEAD, Moves.FIRE_LASH, Moves.DRAGON_DANCE, Moves.GLAIVE_RUSH ],
[Species.BAGON]: [ Moves.FLOATY_FALL, Moves.FIRE_LASH, Moves.DRAGON_DANCE, Moves.GLAIVE_RUSH ],
[Species.BELDUM]: [ Moves.PSYCHIC_FANGS, Moves.RECOVER, Moves.MOUNTAIN_GALE, Moves.SHIFT_GEAR ],
[Species.REGIROCK]: [ Moves.STONE_AXE, Moves.BODY_PRESS, Moves.RECOVER, Moves.SALT_CURE ],
[Species.REGICE]: [ Moves.EARTH_POWER, Moves.COSMIC_POWER, Moves.RECOVER, Moves.FREEZE_DRY ],
[Species.REGISTEEL]: [ Moves.BODY_PRESS, Moves.HEAT_CRASH, Moves.RECOVER, Moves.GIGATON_HAMMER ],
[Species.LATIAS]: [ Moves.CORE_ENFORCER, Moves.SEARING_SHOT, Moves.DRAGON_ENERGY, Moves.QUIVER_DANCE ],
[Species.LATIOS]: [ Moves.CORE_ENFORCER, Moves.SEARING_SHOT, Moves.DRAGON_ENERGY, Moves.QUIVER_DANCE ],
[Species.KYOGRE]: [ Moves.BOUNCY_BUBBLE, Moves.HURRICANE, Moves.THUNDER, Moves.RECOVER ],
[Species.KYOGRE]: [ Moves.BOUNCY_BUBBLE, Moves.HURRICANE, Moves.THUNDER, Moves.TAIL_GLOW ],
[Species.GROUDON]: [ Moves.STONE_AXE, Moves.SOLAR_BLADE, Moves.MORNING_SUN, Moves.SACRED_FIRE ],
[Species.RAYQUAZA]: [ Moves.OBLIVION_WING, Moves.DRAGON_DARTS, Moves.DRAGON_ENERGY, Moves.V_CREATE ],
[Species.JIRACHI]: [ Moves.IRON_HEAD, Moves.FLOATY_FALL, Moves.ROCK_SLIDE, Moves.SHIFT_GEAR ],
@ -215,7 +215,7 @@ export const speciesEggMoves = {
[Species.PACHIRISU]: [ Moves.BADDY_BAD, Moves.SIZZLY_SLIDE, Moves.U_TURN, Moves.ZIPPY_ZAP ],
[Species.BUIZEL]: [ Moves.JET_PUNCH, Moves.TRIPLE_AXEL, Moves.SUPERCELL_SLAM, Moves.SURGING_STRIKES ],
[Species.CHERUBI]: [ Moves.SPORE, Moves.STRENGTH_SAP, Moves.FIERY_DANCE, Moves.FLOWER_TRICK ],
[Species.SHELLOS]: [ Moves.STRENGTH_SAP, Moves.SCORCHING_SANDS, Moves.FREEZE_DRY, Moves.STEAM_ERUPTION ],
[Species.SHELLOS]: [ Moves.BOUNCY_BUBBLE, Moves.SCORCHING_SANDS, Moves.FREEZE_DRY, Moves.STEAM_ERUPTION ],
[Species.DRIFLOON]: [ Moves.WILL_O_WISP, Moves.HEAT_WAVE, Moves.CALM_MIND, Moves.OBLIVION_WING ],
[Species.BUNEARY]: [ Moves.TRIPLE_AXEL, Moves.SWORDS_DANCE, Moves.THUNDEROUS_KICK, Moves.MULTI_ATTACK ],
[Species.GLAMEOW]: [ Moves.U_TURN, Moves.HIGH_HORSEPOWER, Moves.BULK_UP, Moves.EXTREME_SPEED ],
@ -226,7 +226,7 @@ export const speciesEggMoves = {
[Species.MIME_JR]: [ Moves.CALM_MIND, Moves.MOONBLAST, Moves.WILL_O_WISP, Moves.LUMINA_CRASH ],
[Species.HAPPINY]: [ Moves.COTTON_GUARD, Moves.SEISMIC_TOSS, Moves.SIZZLY_SLIDE, Moves.REVIVAL_BLESSING ],
[Species.CHATOT]: [ Moves.SPARKLING_ARIA, Moves.TORCH_SONG, Moves.BATON_PASS, Moves.BOOMBURST ],
[Species.SPIRITOMB]: [ Moves.PARTING_SHOT, Moves.FOUL_PLAY, Moves.RECOVER, Moves.SPECTRAL_THIEF ],
[Species.SPIRITOMB]: [ Moves.PARTING_SHOT, Moves.FOUL_PLAY, Moves.STRENGTH_SAP, Moves.SPECTRAL_THIEF ],
[Species.GIBLE]: [ Moves.DRAGON_DANCE, Moves.THOUSAND_WAVES, Moves.SHORE_UP, Moves.BITTER_BLADE ],
[Species.MUNCHLAX]: [ Moves.CURSE, Moves.BODY_PRESS, Moves.KNOCK_OFF, Moves.SLACK_OFF ],
[Species.RIOLU]: [ Moves.THUNDEROUS_KICK, Moves.BULLET_PUNCH, Moves.TRIPLE_AXEL, Moves.DOUBLE_IRON_BASH ],
@ -237,18 +237,18 @@ export const speciesEggMoves = {
[Species.FINNEON]: [ Moves.QUIVER_DANCE, Moves.BOUNCY_BUBBLE, Moves.FREEZE_DRY, Moves.ORIGIN_PULSE ],
[Species.MANTYKE]: [ Moves.BOUNCY_BUBBLE, Moves.SPIKES, Moves.ROOST, Moves.STEAM_ERUPTION ],
[Species.SNOVER]: [ Moves.HIGH_HORSEPOWER, Moves.STRENGTH_SAP, Moves.AURORA_VEIL, Moves.IVY_CUDGEL ],
[Species.ROTOM]: [ Moves.RECOVER, Moves.FIERY_DANCE, Moves.SPLISHY_SPLASH, Moves.RISING_VOLTAGE ],
[Species.ROTOM]: [ Moves.STRENGTH_SAP, Moves.FIERY_DANCE, Moves.SPLISHY_SPLASH, Moves.RISING_VOLTAGE ],
[Species.UXIE]: [ Moves.COSMIC_POWER, Moves.BODY_PRESS, Moves.RECOVER, Moves.LUMINA_CRASH ],
[Species.MESPRIT]: [ Moves.QUIVER_DANCE, Moves.AURA_SPHERE, Moves.RECOVER, Moves.LUMINA_CRASH ],
[Species.AZELF]: [ Moves.PHOTON_GEYSER, Moves.DRAGON_DANCE, Moves.RECOVER, Moves.LUMINA_CRASH ],
[Species.AZELF]: [ Moves.PHOTON_GEYSER, Moves.ICE_BEAM, Moves.MOONBLAST, Moves.LUMINA_CRASH ],
[Species.DIALGA]: [ Moves.CORE_ENFORCER, Moves.TAKE_HEART, Moves.RECOVER, Moves.MAKE_IT_RAIN ],
[Species.PALKIA]: [ Moves.RECOVER, Moves.TAKE_HEART, Moves.WATER_SPOUT, Moves.DRAGON_ENERGY ],
[Species.HEATRAN]: [ Moves.TORCH_SONG, Moves.RECOVER, Moves.FLASH_CANNON, Moves.MATCHA_GOTCHA ],
[Species.REGIGIGAS]: [ Moves.SKILL_SWAP, Moves.SHORE_UP, Moves.EXTREME_SPEED, Moves.GIGATON_HAMMER ],
[Species.GIRATINA]: [ Moves.DRAGON_DANCE, Moves.GLAIVE_RUSH, Moves.RECOVER, Moves.ASTRAL_BARRAGE ],
[Species.GIRATINA]: [ Moves.DRAGON_DANCE, Moves.GLAIVE_RUSH, Moves.RECOVER, Moves.SPECTRAL_THIEF ],
[Species.CRESSELIA]: [ Moves.COSMIC_POWER, Moves.SECRET_SWORD, Moves.SIZZLY_SLIDE, Moves.LUMINA_CRASH ],
[Species.PHIONE]: [ Moves.BOUNCY_BUBBLE, Moves.FREEZE_DRY, Moves.RECOVER, Moves.QUIVER_DANCE ],
[Species.MANAPHY]: [ Moves.BOUNCY_BUBBLE, Moves.FREEZE_DRY, Moves.RECOVER, Moves.QUIVER_DANCE ],
[Species.PHIONE]: [ Moves.BOUNCY_BUBBLE, Moves.FREEZE_DRY, Moves.SPLISHY_SPLASH, Moves.QUIVER_DANCE ],
[Species.MANAPHY]: [ Moves.BOUNCY_BUBBLE, Moves.FREEZE_DRY, Moves.SPLISHY_SPLASH, Moves.QUIVER_DANCE ],
[Species.DARKRAI]: [ Moves.FIERY_WRATH, Moves.MOONBLAST, Moves.SEARING_SHOT, Moves.SPORE ],
[Species.SHAYMIN]: [ Moves.SPRINGTIDE_STORM, Moves.HEAT_WAVE, Moves.BLEAKWIND_STORM, Moves.MATCHA_GOTCHA ],
[Species.ARCEUS]: [ Moves.QUIVER_DANCE, Moves.COLLISION_COURSE, Moves.VICTORY_DANCE, Moves.SPECTRAL_THIEF ],
@ -303,7 +303,7 @@ export const speciesEggMoves = {
[Species.JOLTIK]: [ Moves.THUNDER, Moves.PARABOLIC_CHARGE, Moves.EARTH_POWER, Moves.QUIVER_DANCE ],
[Species.FERROSEED]: [ Moves.STRENGTH_SAP, Moves.BODY_PRESS, Moves.SPIKY_SHIELD, Moves.SAPPY_SEED ],
[Species.KLINK]: [ Moves.FLARE_BLITZ, Moves.HIGH_HORSEPOWER, Moves.FUSION_BOLT, Moves.DOUBLE_IRON_BASH ],
[Species.TYNAMO]: [ Moves.SCALD, Moves.RECOVER, Moves.FIRE_LASH, Moves.PLASMA_FISTS ],
[Species.TYNAMO]: [ Moves.SCALD, Moves.STRENGTH_SAP, Moves.FIRE_LASH, Moves.PLASMA_FISTS ],
[Species.ELGYEM]: [ Moves.MYSTICAL_POWER, Moves.TRICK_ROOM, Moves.STORED_POWER, Moves.LUMINA_CRASH ],
[Species.LITWICK]: [ Moves.FIERY_DANCE, Moves.EARTH_POWER, Moves.MOONBLAST, Moves.ASTRAL_BARRAGE ],
[Species.AXEW]: [ Moves.STONE_AXE, Moves.DIRE_CLAW, Moves.FIRE_LASH, Moves.GLAIVE_RUSH ],
@ -313,7 +313,7 @@ export const speciesEggMoves = {
[Species.STUNFISK]: [ Moves.SHORE_UP, Moves.BANEFUL_BUNKER, Moves.THUNDER_CAGE, Moves.THUNDERCLAP ],
[Species.MIENFOO]: [ Moves.GUNK_SHOT, Moves.SUPERCELL_SLAM, Moves.KNOCK_OFF, Moves.MOUNTAIN_GALE ],
[Species.DRUDDIGON]: [ Moves.GLARE, Moves.ROOST, Moves.DRAGON_HAMMER, Moves.FIRE_LASH ],
[Species.GOLETT]: [ Moves.BULK_UP, Moves.RECOVER, Moves.HEADLONG_RUSH, Moves.RAGE_FIST ],
[Species.GOLETT]: [ Moves.SHIFT_GEAR, Moves.DRAIN_PUNCH, Moves.HEADLONG_RUSH, Moves.RAGE_FIST ],
[Species.PAWNIARD]: [ Moves.SUCKER_PUNCH, Moves.CEASELESS_EDGE, Moves.BITTER_BLADE, Moves.LAST_RESPECTS ],
[Species.BOUFFALANT]: [ Moves.SLACK_OFF, Moves.JUMP_KICK, Moves.HEAD_SMASH, Moves.FLARE_BLITZ ],
[Species.RUFFLET]: [ Moves.FLOATY_FALL, Moves.MOONBLAST, Moves.HEAT_WAVE, Moves.BOLT_BEAK ],
@ -328,14 +328,14 @@ export const speciesEggMoves = {
[Species.TORNADUS]: [ Moves.EARTH_POWER, Moves.U_TURN, Moves.ICE_BEAM, Moves.OBLIVION_WING ],
[Species.THUNDURUS]: [ Moves.EARTH_POWER, Moves.HURRICANE, Moves.THUNDERCLAP, Moves.ELECTRO_SHOT ],
[Species.RESHIRAM]: [ Moves.ROOST, Moves.TAKE_HEART, Moves.ERUPTION, Moves.DRAGON_ENERGY ],
[Species.ZEKROM]: [ Moves.ROOST, Moves.THUNDEROUS_KICK, Moves.DRAGON_HAMMER, Moves.BOLT_BEAK ],
[Species.ZEKROM]: [ Moves.DRAGON_DANCE, Moves.THUNDEROUS_KICK, Moves.DRAGON_HAMMER, Moves.BOLT_BEAK ],
[Species.LANDORUS]: [ Moves.STONE_AXE, Moves.THOUSAND_ARROWS, Moves.ROOST, Moves.FLOATY_FALL ],
[Species.KYUREM]: [ Moves.ICICLE_CRASH, Moves.DRAGON_ENERGY, Moves.NASTY_PLOT, Moves.GLACIAL_LANCE ],
[Species.KELDEO]: [ Moves.BOUNCY_BUBBLE, Moves.THUNDERBOLT, Moves.FREEZE_DRY, Moves.STEAM_ERUPTION ],
[Species.MELOETTA]: [ Moves.TORCH_SONG, Moves.QUIVER_DANCE, Moves.THUNDEROUS_KICK, Moves.BOOMBURST ],
[Species.GENESECT]: [ Moves.EXTREME_SPEED, Moves.U_TURN, Moves.SHIFT_GEAR, Moves.TAIL_GLOW ],
[Species.CHESPIN]: [ Moves.DRAIN_PUNCH, Moves.SYNTHESIS, Moves.CEASELESS_EDGE, Moves.SAPPY_SEED ],
[Species.FENNEKIN]: [ Moves.BITTER_MALICE, Moves.MOONBLAST, Moves.THUNDERBOLT, Moves.TORCH_SONG ],
[Species.FENNEKIN]: [ Moves.EXPANDING_FORCE, Moves.MOONBLAST, Moves.THUNDERBOLT, Moves.TORCH_SONG ],
[Species.FROAKIE]: [ Moves.MOONBLAST, Moves.EARTH_POWER, Moves.TRIPLE_AXEL, Moves.SURGING_STRIKES ],
[Species.BUNNELBY]: [ Moves.DRAIN_PUNCH, Moves.TIDY_UP, Moves.FACADE, Moves.EXTREME_SPEED ],
[Species.FLETCHLING]: [ Moves.DRILL_RUN, Moves.U_TURN, Moves.SUPERCELL_SLAM, Moves.TIDY_UP ],
@ -346,14 +346,14 @@ export const speciesEggMoves = {
[Species.PANCHAM]: [ Moves.DRAIN_PUNCH, Moves.FAKE_OUT, Moves.BULLET_PUNCH, Moves.WICKED_BLOW ],
[Species.FURFROU]: [ Moves.TIDY_UP, Moves.CRUNCH, Moves.COVET, Moves.MULTI_ATTACK ],
[Species.ESPURR]: [ Moves.GLARE, Moves.MOONBLAST, Moves.FLAMETHROWER, Moves.PSYSTRIKE ],
[Species.HONEDGE]: [ Moves.TACHYON_CUTTER, Moves.POLTERGEIST, Moves.BITTER_BLADE, Moves.PAIN_SPLIT ],
[Species.HONEDGE]: [ Moves.TACHYON_CUTTER, Moves.POLTERGEIST, Moves.BITTER_BLADE, Moves.BEHEMOTH_BLADE ],
[Species.SPRITZEE]: [ Moves.TRICK_ROOM, Moves.FOUL_PLAY, Moves.WISH, Moves.REVIVAL_BLESSING ],
[Species.SWIRLIX]: [ Moves.BELLY_DRUM, Moves.SUCKER_PUNCH, Moves.SPIRIT_BREAK, Moves.SIZZLY_SLIDE ],
[Species.INKAY]: [ Moves.POWER_TRIP, Moves.STORED_POWER, Moves.RECOVER, Moves.PSYCHO_BOOST ],
[Species.BINACLE]: [ Moves.ICE_SPINNER, Moves.ACCELEROCK, Moves.BULK_UP, Moves.MIGHTY_CLEAVE ],
[Species.BINACLE]: [ Moves.TRIPLE_AXEL, Moves.ACCELEROCK, Moves.DIRE_CLAW, Moves.MIGHTY_CLEAVE ],
[Species.SKRELP]: [ Moves.RECOVER, Moves.CORE_ENFORCER, Moves.CALM_MIND, Moves.MALIGNANT_CHAIN ],
[Species.CLAUNCHER]: [ Moves.SHELL_SMASH, Moves.ARMOR_CANNON, Moves.TERRAIN_PULSE, Moves.ORIGIN_PULSE ],
[Species.HELIOPTILE]: [ Moves.WEATHER_BALL, Moves.NASTY_PLOT, Moves.SHORE_UP, Moves.CLANGOROUS_SOUL ],
[Species.HELIOPTILE]: [ Moves.WEATHER_BALL, Moves.BOOMBURST, Moves.EARTH_POWER, Moves.TAIL_GLOW ],
[Species.TYRUNT]: [ Moves.DRAGON_HAMMER, Moves.FLARE_BLITZ, Moves.VOLT_TACKLE, Moves.AXE_KICK ],
[Species.AMAURA]: [ Moves.RECOVER, Moves.AURORA_VEIL, Moves.POWER_GEM, Moves.GEOMANCY ],
[Species.HAWLUCHA]: [ Moves.DARKEST_LARIAT, Moves.HIGH_HORSEPOWER, Moves.SUPERCELL_SLAM, Moves.BRAVE_BIRD ],
@ -361,13 +361,13 @@ export const speciesEggMoves = {
[Species.CARBINK]: [ Moves.BODY_PRESS, Moves.SHORE_UP, Moves.SPARKLY_SWIRL, Moves.DIAMOND_STORM ],
[Species.GOOMY]: [ Moves.SCALD, Moves.RECOVER, Moves.CALM_MIND, Moves.MAKE_IT_RAIN ],
[Species.KLEFKI]: [ Moves.COURT_CHANGE, Moves.ENCORE, Moves.TAUNT, Moves.TOPSY_TURVY ],
[Species.PHANTUMP]: [ Moves.POLTERGEIST, Moves.TRICK_ROOM, Moves.SYNTHESIS, Moves.SAPPY_SEED ],
[Species.PUMPKABOO]: [ Moves.POLTERGEIST, Moves.FIRE_LASH, Moves.DIRE_CLAW, Moves.SAPPY_SEED ],
[Species.PHANTUMP]: [ Moves.SPIRIT_SHACKLE, Moves.TRICK_ROOM, Moves.SYNTHESIS, Moves.SAPPY_SEED ],
[Species.PUMPKABOO]: [ Moves.SPIRIT_SHACKLE, Moves.FIRE_LASH, Moves.DIRE_CLAW, Moves.SAPPY_SEED ],
[Species.BERGMITE]: [ Moves.STONE_AXE, Moves.METAL_BURST, Moves.BODY_PRESS, Moves.GLACIAL_LANCE ],
[Species.NOIBAT]: [ Moves.AEROBLAST, Moves.OVERDRIVE, Moves.NASTY_PLOT, Moves.CLANGING_SCALES ],
[Species.XERNEAS]: [ Moves.LIGHT_OF_RUIN, Moves.LUMINA_CRASH, Moves.STRENGTH_SAP, Moves.REVIVAL_BLESSING ],
[Species.YVELTAL]: [ Moves.IRON_HEAD, Moves.FLOATY_FALL, Moves.NASTY_PLOT, Moves.WICKED_BLOW ],
[Species.ZYGARDE]: [ Moves.DRAGON_DARTS, Moves.SHORE_UP, Moves.VICTORY_DANCE, Moves.DOUBLE_IRON_BASH ],
[Species.YVELTAL]: [ Moves.SLUDGE_WAVE, Moves.POWER_TRIP, Moves.FIERY_WRATH, Moves.CLANGOROUS_SOUL ],
[Species.ZYGARDE]: [ Moves.DRAGON_DARTS, Moves.HEAL_ORDER, Moves.VICTORY_DANCE, Moves.DOUBLE_IRON_BASH ],
[Species.DIANCIE]: [ Moves.MAGICAL_TORQUE, Moves.BODY_PRESS, Moves.SHORE_UP, Moves.GEOMANCY ],
[Species.HOOPA]: [ Moves.PHOTON_GEYSER, Moves.EARTH_POWER, Moves.BATON_PASS, Moves.TIDY_UP ],
[Species.VOLCANION]: [ Moves.HYDRO_STEAM, Moves.CALM_MIND, Moves.ENERGY_BALL, Moves.SEARING_SHOT ],
@ -400,38 +400,38 @@ export const speciesEggMoves = {
[Species.MINIOR]: [ Moves.EARTH_POWER, Moves.FLOATY_FALL, Moves.ZING_ZAP, Moves.DIAMOND_STORM ],
[Species.KOMALA]: [ Moves.SLACK_OFF, Moves.EXTREME_SPEED, Moves.KNOCK_OFF, Moves.CLOSE_COMBAT ],
[Species.TURTONATOR]: [ Moves.SHELL_SMASH, Moves.ARMOR_CANNON, Moves.EARTH_POWER, Moves.CLANGING_SCALES ],
[Species.TOGEDEMARU]: [ Moves.SIZZLY_SLIDE, Moves.RECOVER, Moves.METEOR_MASH, Moves.BEHEMOTH_BASH ],
[Species.MIMIKYU]: [ Moves.SPIRIT_BREAK, Moves.NUZZLE, Moves.PARTING_SHOT, Moves.SPECTRAL_THIEF ],
[Species.TOGEDEMARU]: [ Moves.FAKE_OUT, Moves.METAL_BURST, Moves.METEOR_MASH, Moves.BOLT_STRIKE ],
[Species.MIMIKYU]: [ Moves.SPIRIT_BREAK, Moves.TIDY_UP, Moves.SIZZLY_SLIDE, Moves.SPECTRAL_THIEF ],
[Species.BRUXISH]: [ Moves.ICE_FANG, Moves.FIRE_FANG, Moves.FLIP_TURN, Moves.FILLET_AWAY ],
[Species.DRAMPA]: [ Moves.SLACK_OFF, Moves.FLAMETHROWER, Moves.CLANGING_SCALES, Moves.CLANGOROUS_SOUL ],
[Species.DHELMISE]: [ Moves.POLTERGEIST, Moves.STRENGTH_SAP, Moves.LEAF_BLADE, Moves.DOUBLE_IRON_BASH ],
[Species.JANGMO_O]: [ Moves.ICE_BEAM, Moves.RECOVER, Moves.SECRET_SWORD, Moves.GLAIVE_RUSH ],
[Species.JANGMO_O]: [ Moves.ICE_BEAM, Moves.DRAIN_PUNCH, Moves.SECRET_SWORD, Moves.GLAIVE_RUSH ],
[Species.TAPU_KOKO]: [ Moves.PLAY_ROUGH, Moves.MOUNTAIN_GALE, Moves.RISING_VOLTAGE, Moves.BOLT_BEAK ],
[Species.TAPU_LELE]: [ Moves.MOONLIGHT, Moves.NASTY_PLOT, Moves.HEAT_WAVE, Moves.EXPANDING_FORCE ],
[Species.TAPU_BULU]: [ Moves.GRASSY_GLIDE, Moves.CLOSE_COMBAT, Moves.PLAY_ROUGH, Moves.VICTORY_DANCE ],
[Species.TAPU_FINI]: [ Moves.AURA_SPHERE, Moves.EARTH_POWER, Moves.RECOVER, Moves.QUIVER_DANCE ],
[Species.COSMOG]: [ Moves.VICTORY_DANCE, Moves.QUIVER_DANCE, Moves.STORED_POWER, Moves.PHOTON_GEYSER ],
[Species.NIHILEGO]: [ Moves.RECOVER, Moves.QUIVER_DANCE, Moves.GIGA_DRAIN, Moves.MALIGNANT_CHAIN ],
[Species.NIHILEGO]: [ Moves.RECOVER, Moves.QUIVER_DANCE, Moves.ENERGY_BALL, Moves.MALIGNANT_CHAIN ],
[Species.BUZZWOLE]: [ Moves.LEECH_LIFE, Moves.BULLET_PUNCH, Moves.DARKEST_LARIAT, Moves.COLLISION_COURSE ],
[Species.PHEROMOSA]: [ Moves.AURA_SPHERE, Moves.MAKE_IT_RAIN, Moves.ATTACK_ORDER, Moves.COLLISION_COURSE ],
[Species.XURKITREE]: [ Moves.OVERHEAT, Moves.GIGA_DRAIN, Moves.TAIL_GLOW, Moves.THUNDERCLAP ],
[Species.CELESTEELA]: [ Moves.ROOST, Moves.BUZZY_BUZZ, Moves.SPIKES, Moves.OBLIVION_WING ],
[Species.KARTANA]: [ Moves.MIGHTY_CLEAVE, Moves.CEASELESS_EDGE, Moves.BITTER_BLADE, Moves.BEHEMOTH_BLADE ],
[Species.GUZZLORD]: [ Moves.DIRE_CLAW, Moves.GLAIVE_RUSH, Moves.SLACK_OFF, Moves.BADDY_BAD ],
[Species.GUZZLORD]: [ Moves.SUCKER_PUNCH, Moves.COMEUPPANCE, Moves.SLACK_OFF, Moves.RUINATION ],
[Species.NECROZMA]: [ Moves.COSMIC_POWER, Moves.SACRED_FIRE, Moves.ASTRAL_BARRAGE, Moves.CLANGOROUS_SOUL ],
[Species.MAGEARNA]: [ Moves.RECOVER, Moves.EARTH_POWER, Moves.COSMIC_POWER, Moves.MAKE_IT_RAIN ],
[Species.MAGEARNA]: [ Moves.STRENGTH_SAP, Moves.EARTH_POWER, Moves.COSMIC_POWER, Moves.MAKE_IT_RAIN ],
[Species.MARSHADOW]: [ Moves.POWER_UP_PUNCH, Moves.TRIPLE_AXEL, Moves.STORM_THROW, Moves.DOUBLE_IRON_BASH ],
[Species.POIPOLE]: [ Moves.SLUDGE_BOMB, Moves.BUG_BUZZ, Moves.SEARING_SHOT, Moves.DRAGON_ENERGY ],
[Species.STAKATAKA]: [ Moves.HEAVY_SLAM, Moves.SHORE_UP, Moves.CURSE, Moves.SALT_CURE ],
[Species.BLACEPHALON]: [ Moves.NASTY_PLOT, Moves.SEARING_SHOT, Moves.GIGA_DRAIN, Moves.ASTRAL_BARRAGE ],
[Species.ZERAORA]: [ Moves.SWORDS_DANCE, Moves.TRIPLE_AXEL, Moves.BOLT_STRIKE, Moves.PYRO_BALL ],
[Species.MELTAN]: [ Moves.BULLET_PUNCH, Moves.DRAIN_PUNCH, Moves.BULK_UP, Moves.RECOVER ],
[Species.MELTAN]: [ Moves.BULLET_PUNCH, Moves.DRAIN_PUNCH, Moves.BULK_UP, Moves.PLASMA_FISTS ],
[Species.GROOKEY]: [ Moves.HEADLONG_RUSH, Moves.CLOSE_COMBAT, Moves.GRASSY_GLIDE, Moves.CLANGOROUS_SOUL ],
[Species.SCORBUNNY]: [ Moves.EXTREME_SPEED, Moves.TROP_KICK, Moves.TRIPLE_AXEL, Moves.THUNDEROUS_KICK ],
[Species.SOBBLE]: [ Moves.AEROBLAST, Moves.FROST_BREATH, Moves.SEARING_SHOT, Moves.SURGING_STRIKES ],
[Species.SKWOVET]: [ Moves.KNOCK_OFF, Moves.GRAV_APPLE, Moves.BODY_PRESS, Moves.SLACK_OFF ],
[Species.ROOKIDEE]: [ Moves.ROOST, Moves.BODY_PRESS, Moves.IRON_HEAD, Moves.KINGS_SHIELD ],
[Species.BLIPBUG]: [ Moves.RECOVER, Moves.FREEZING_GLARE, Moves.SPORE, Moves.TAIL_GLOW ],
[Species.BLIPBUG]: [ Moves.HEAL_ORDER, Moves.EXPANDING_FORCE, Moves.SPORE, Moves.TAIL_GLOW ],
[Species.NICKIT]: [ Moves.BADDY_BAD, Moves.BURNING_JEALOUSY, Moves.SPARKLY_SWIRL, Moves.FIERY_WRATH ],
[Species.GOSSIFLEUR]: [ Moves.TAILWIND, Moves.STRENGTH_SAP, Moves.PARTING_SHOT, Moves.SEED_FLARE ],
[Species.WOOLOO]: [ Moves.PSYSHIELD_BASH, Moves.HEAD_CHARGE, Moves.BODY_PRESS, Moves.MILK_DRINK ],
@ -440,7 +440,7 @@ export const speciesEggMoves = {
[Species.ROLYCOLY]: [ Moves.BURNING_BULWARK, Moves.ZING_ZAP, Moves.WORK_UP, Moves.DIAMOND_STORM ],
[Species.APPLIN]: [ Moves.DRAGON_CHEER, Moves.PARTING_SHOT, Moves.FLOWER_TRICK, Moves.STRENGTH_SAP ],
[Species.SILICOBRA]: [ Moves.SHORE_UP, Moves.SHED_TAIL, Moves.STONE_EDGE, Moves.PRECIPICE_BLADES ],
[Species.CRAMORANT]: [ Moves.APPLE_ACID, Moves.SURF, Moves.SCORCHING_SANDS, Moves.ROOST ],
[Species.CRAMORANT]: [ Moves.APPLE_ACID, Moves.SURF, Moves.SCORCHING_SANDS, Moves.OBLIVION_WING ],
[Species.ARROKUDA]: [ Moves.THUNDER_FANG, Moves.KNOCK_OFF, Moves.ICE_FANG, Moves.FILLET_AWAY ],
[Species.TOXEL]: [ Moves.NASTY_PLOT, Moves.BANEFUL_BUNKER, Moves.SPARKLING_ARIA, Moves.TORCH_SONG ],
[Species.SIZZLIPEDE]: [ Moves.BURNING_BULWARK, Moves.ZING_ZAP, Moves.FIRST_IMPRESSION, Moves.VICTORY_DANCE ],
@ -461,8 +461,8 @@ export const speciesEggMoves = {
[Species.ARCTOZOLT]: [ Moves.TRIPLE_AXEL, Moves.LIQUIDATION, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ],
[Species.DRACOVISH]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.THUNDER_FANG, Moves.DRAGON_DANCE ],
[Species.ARCTOVISH]: [ Moves.TRIPLE_AXEL, Moves.SUPERCELL_SLAM, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ],
[Species.DURALUDON]: [ Moves.CALM_MIND, Moves.BODY_PRESS, Moves.EARTH_POWER, Moves.RECOVER ],
[Species.DREEPY]: [ Moves.DRAGON_ENERGY, Moves.SHED_TAIL, Moves.BLAZING_TORQUE, Moves.SPECTRAL_THIEF ],
[Species.DURALUDON]: [ Moves.ICE_BEAM, Moves.BODY_PRESS, Moves.RECOVER, Moves.CORE_ENFORCER ],
[Species.DREEPY]: [ Moves.DRAGON_ENERGY, Moves.SPIRIT_BREAK, Moves.BLAZING_TORQUE, Moves.SPECTRAL_THIEF ],
[Species.ZACIAN]: [ Moves.MAGICAL_TORQUE, Moves.BITTER_BLADE, Moves.LEAF_BLADE, Moves.VICTORY_DANCE ],
[Species.ZAMAZENTA]: [ Moves.PSYSHIELD_BASH, Moves.BODY_PRESS, Moves.SLACK_OFF, Moves.VICTORY_DANCE ],
[Species.KUBFU]: [ Moves.METEOR_MASH, Moves.DRAIN_PUNCH, Moves.JET_PUNCH, Moves.DRAGON_DANCE ],
@ -471,11 +471,11 @@ export const speciesEggMoves = {
[Species.REGIDRAGO]: [ Moves.METEOR_MASH, Moves.FLAMETHROWER, Moves.CALM_MIND, Moves.DRAGON_DARTS ],
[Species.GLASTRIER]: [ Moves.TRICK_ROOM, Moves.SLACK_OFF, Moves.HIGH_HORSEPOWER, Moves.GLACIAL_LANCE ],
[Species.SPECTRIER]: [ Moves.EARTH_POWER, Moves.PARTING_SHOT, Moves.AURA_SPHERE, Moves.ASTRAL_BARRAGE ],
[Species.CALYREX]: [ Moves.SAPPY_SEED, Moves.RECOVER, Moves.AURA_SPHERE, Moves.PHOTON_GEYSER ],
[Species.CALYREX]: [ Moves.SAPPY_SEED, Moves.RECOVER, Moves.SECRET_SWORD, Moves.PHOTON_GEYSER ],
[Species.ENAMORUS]: [ Moves.FLEUR_CANNON, Moves.TAKE_HEART, Moves.STORED_POWER, Moves.OBLIVION_WING ],
[Species.SPRIGATITO]: [ Moves.BLAZE_KICK, Moves.STRENGTH_SAP, Moves.SUCKER_PUNCH, Moves.WICKED_BLOW ],
[Species.FUECOCO]: [ Moves.COSMIC_POWER, Moves.SLACK_OFF, Moves.INFERNAL_PARADE, Moves.MOONGEIST_BEAM ],
[Species.QUAXLY]: [ Moves.DRAGON_DANCE, Moves.ROOST, Moves.TROP_KICK, Moves.THUNDEROUS_KICK ],
[Species.SPRIGATITO]: [ Moves.FIRE_LASH, Moves.TRIPLE_AXEL, Moves.SUCKER_PUNCH, Moves.WICKED_BLOW ],
[Species.FUECOCO]: [ Moves.ALLURING_VOICE, Moves.SLACK_OFF, Moves.OVERDRIVE, Moves.MOONGEIST_BEAM ],
[Species.QUAXLY]: [ Moves.DRAGON_DANCE, Moves.TRIPLE_AXEL, Moves.TROP_KICK, Moves.THUNDEROUS_KICK ],
[Species.LECHONK]: [ Moves.MILK_DRINK, Moves.BLAZING_TORQUE, Moves.FILLET_AWAY, Moves.MULTI_ATTACK ],
[Species.TAROUNTULA]: [ Moves.STONE_AXE, Moves.LEECH_LIFE, Moves.THIEF, Moves.SPORE ],
[Species.NYMBLE]: [ Moves.CEASELESS_EDGE, Moves.FELL_STINGER, Moves.LEECH_LIFE, Moves.WICKED_BLOW ],
@ -485,13 +485,13 @@ export const speciesEggMoves = {
[Species.SMOLIV]: [ Moves.STRENGTH_SAP, Moves.EARTH_POWER, Moves.CALM_MIND, Moves.BOOMBURST ],
[Species.SQUAWKABILLY]: [ Moves.PARTING_SHOT, Moves.BULK_UP, Moves.FLARE_BLITZ, Moves.HEAD_CHARGE ],
[Species.NACLI]: [ Moves.BODY_PRESS, Moves.SPIKES, Moves.CURSE, Moves.DIAMOND_STORM ],
[Species.CHARCADET]: [ Moves.SACRED_SWORD, Moves.PHOTON_GEYSER, Moves.RECOVER, Moves.SPECTRAL_THIEF ],
[Species.CHARCADET]: [ Moves.SACRED_SWORD, Moves.PHOTON_GEYSER, Moves.MOONBLAST, Moves.SPECTRAL_THIEF ],
[Species.TADBULB]: [ Moves.PARABOLIC_CHARGE, Moves.SCALD, Moves.EARTH_POWER, Moves.ELECTRO_SHOT ],
[Species.WATTREL]: [ Moves.NASTY_PLOT, Moves.TAILWIND, Moves.HEAT_WAVE, Moves.AEROBLAST ],
[Species.MASCHIFF]: [ Moves.PARTING_SHOT, Moves.KNOCK_OFF, Moves.NUZZLE, Moves.COLLISION_COURSE ],
[Species.SHROODLE]: [ Moves.FIRE_LASH, Moves.PARTING_SHOT, Moves.TOXIC, Moves.TOPSY_TURVY ],
[Species.BRAMBLIN]: [ Moves.TAILWIND, Moves.STRENGTH_SAP, Moves.CEASELESS_EDGE, Moves.LAST_RESPECTS ],
[Species.TOEDSCOOL]: [ Moves.STRENGTH_SAP, Moves.HEART_SWAP, Moves.PARTING_SHOT, Moves.SAPPY_SEED ],
[Species.TOEDSCOOL]: [ Moves.STRENGTH_SAP, Moves.TOPSY_TURVY, Moves.PARTING_SHOT, Moves.SAPPY_SEED ],
[Species.KLAWF]: [ Moves.CRABHAMMER, Moves.SHORE_UP, Moves.MIGHTY_CLEAVE, Moves.SHELL_SMASH ],
[Species.CAPSAKID]: [ Moves.STRENGTH_SAP, Moves.APPLE_ACID, Moves.FROST_BREATH, Moves.TORCH_SONG ],
[Species.RELLOR]: [ Moves.TOXIC_SPIKES, Moves.RECOVER, Moves.HEAT_WAVE, Moves.LUMINA_CRASH ],
@ -499,7 +499,7 @@ export const speciesEggMoves = {
[Species.TINKATINK]: [ Moves.NUZZLE, Moves.SHIFT_GEAR, Moves.ICE_HAMMER, Moves.PYRO_BALL ],
[Species.WIGLETT]: [ Moves.SHELL_SMASH, Moves.ICICLE_CRASH, Moves.SEED_BOMB, Moves.SURGING_STRIKES ],
[Species.BOMBIRDIER]: [ Moves.U_TURN, Moves.TIDY_UP, Moves.SUCKER_PUNCH, Moves.MIGHTY_CLEAVE ],
[Species.FINIZEN]: [ Moves.TRIPLE_AXEL, Moves.DRAIN_PUNCH, Moves.RECOVER, Moves.WOOD_HAMMER ],
[Species.FINIZEN]: [ Moves.TRIPLE_AXEL, Moves.DRAIN_PUNCH, Moves.HEADLONG_RUSH, Moves.SURGING_STRIKES ],
[Species.VAROOM]: [ Moves.COMBAT_TORQUE, Moves.U_TURN, Moves.BLAZING_TORQUE, Moves.NOXIOUS_TORQUE ],
[Species.CYCLIZAR]: [ Moves.BATON_PASS, Moves.BLAZING_TORQUE, Moves.HEAD_CHARGE, Moves.CLANGOROUS_SOUL ],
[Species.ORTHWORM]: [ Moves.GLARE, Moves.COIL, Moves.BODY_PRESS, Moves.SHORE_UP ],
@ -518,24 +518,24 @@ export const speciesEggMoves = {
[Species.SANDY_SHOCKS]: [ Moves.SHORE_UP, Moves.ICE_BEAM, Moves.NASTY_PLOT, Moves.THUNDERCLAP ],
[Species.IRON_TREADS]: [ Moves.SUPERCELL_SLAM, Moves.BULK_UP, Moves.SHORE_UP, Moves.DOUBLE_IRON_BASH ],
[Species.IRON_BUNDLE]: [ Moves.EARTH_POWER, Moves.BOUNCY_BUBBLE, Moves.NASTY_PLOT, Moves.WATER_SPOUT ],
[Species.IRON_HANDS]: [ Moves.DRAIN_PUNCH, Moves.CURSE, Moves.PLASMA_FISTS, Moves.RECOVER ],
[Species.IRON_HANDS]: [ Moves.DRAIN_PUNCH, Moves.BULK_UP, Moves.PLASMA_FISTS, Moves.ICE_HAMMER ],
[Species.IRON_JUGULIS]: [ Moves.FIERY_WRATH, Moves.ROOST, Moves.NASTY_PLOT, Moves.OBLIVION_WING ],
[Species.IRON_MOTH]: [ Moves.EARTH_POWER, Moves.SEARING_SHOT, Moves.QUIVER_DANCE, Moves.MALIGNANT_CHAIN ],
[Species.IRON_THORNS]: [ Moves.MIGHTY_CLEAVE, Moves.SHORE_UP, Moves.SHIFT_GEAR, Moves.FUSION_BOLT ],
[Species.FRIGIBAX]: [ Moves.DRAGON_DARTS, Moves.BULK_UP, Moves.SHORE_UP, Moves.GLACIAL_LANCE ],
[Species.GIMMIGHOUL]: [ Moves.COSMIC_POWER, Moves.STORED_POWER, Moves.BATON_PASS, Moves.ASTRAL_BARRAGE ],
[Species.WO_CHIEN]: [ Moves.SPORE, Moves.RAGE_POWDER, Moves.SAPPY_SEED, Moves.RECOVER ],
[Species.WO_CHIEN]: [ Moves.SPORE, Moves.RAGE_POWDER, Moves.SAPPY_SEED, Moves.STRENGTH_SAP ],
[Species.CHIEN_PAO]: [ Moves.KNOCK_OFF, Moves.PARTING_SHOT, Moves.BITTER_BLADE, Moves.GLACIAL_LANCE ],
[Species.TING_LU]: [ Moves.SHORE_UP, Moves.CURSE, Moves.SAPPY_SEED, Moves.THOUSAND_ARROWS ],
[Species.CHI_YU]: [ Moves.FIERY_WRATH, Moves.HYDRO_STEAM, Moves.TORCH_SONG, Moves.ERUPTION ],
[Species.ROARING_MOON]: [ Moves.FIRE_LASH, Moves.DRAGON_HAMMER, Moves.SUCKER_PUNCH, Moves.WICKED_BLOW ],
[Species.IRON_VALIANT]: [ Moves.PLASMA_FISTS, Moves.VICTORY_DANCE, Moves.QUIVER_DANCE, Moves.MAGICAL_TORQUE ],
[Species.KORAIDON]: [ Moves.SACRED_FIRE, Moves.RECOVER, Moves.GLAIVE_RUSH, Moves.CLANGOROUS_SOUL ],
[Species.MIRAIDON]: [ Moves.ICE_BEAM, Moves.RECOVER, Moves.RISING_VOLTAGE, Moves.DRAGON_ENERGY ],
[Species.KORAIDON]: [ Moves.BITTER_BLADE, Moves.MORNING_SUN, Moves.GLAIVE_RUSH, Moves.CLANGOROUS_SOUL ],
[Species.MIRAIDON]: [ Moves.ICE_BEAM, Moves.CLANGOROUS_SOUL, Moves.RISING_VOLTAGE, Moves.DRAGON_ENERGY ],
[Species.WALKING_WAKE]: [ Moves.BOUNCY_BUBBLE, Moves.NASTY_PLOT, Moves.EARTH_POWER, Moves.DRAGON_ENERGY ],
[Species.IRON_LEAVES]: [ Moves.SPORE, Moves.U_TURN, Moves.MIGHTY_CLEAVE, Moves.BITTER_BLADE ],
[Species.POLTCHAGEIST]: [ Moves.COSMIC_POWER, Moves.INFERNAL_PARADE, Moves.LEECH_SEED, Moves.SPARKLY_SWIRL ],
[Species.OKIDOGI]: [ Moves.MORNING_SUN, Moves.OBSTRUCT, Moves.DIRE_CLAW, Moves.COLLISION_COURSE ],
[Species.OKIDOGI]: [ Moves.SLACK_OFF, Moves.OBSTRUCT, Moves.DIRE_CLAW, Moves.COLLISION_COURSE ],
[Species.MUNKIDORI]: [ Moves.PSYSTRIKE, Moves.HEAT_WAVE, Moves.EARTH_POWER, Moves.MALIGNANT_CHAIN ],
[Species.FEZANDIPITI]: [ Moves.BATON_PASS, Moves.COSMIC_POWER, Moves.SIZZLY_SLIDE, Moves.MALIGNANT_CHAIN ],
[Species.OGERPON]: [ Moves.FLOWER_TRICK, Moves.BONEMERANG, Moves.TRIPLE_AXEL, Moves.GIGATON_HAMMER ],

View File

@ -1,313 +1,624 @@
export enum Abilities {
/**{@link https://bulbapedia.bulbagarden.net/wiki/None_(ability) | Source} */
NONE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stench_(ability) | Source} */
STENCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Drizzle_(ability) | Source} */
DRIZZLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Speed_Boost_(ability) | Source} */
SPEED_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Battle_Armor_(ability) | Source} */
BATTLE_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sturdy_(ability) | Source} */
STURDY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Damp_(ability) | Source} */
DAMP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Limber_(ability) | Source} */
LIMBER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Veil_(ability) | Source} */
SAND_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Static_(ability) | Source} */
STATIC,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Volt_Absorb_(ability) | Source} */
VOLT_ABSORB,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Absorb_(ability) | Source} */
WATER_ABSORB,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Oblivious_(ability) | Source} */
OBLIVIOUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cloud_Nine_(ability) | Source} */
CLOUD_NINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Compound_Eyes_(ability) | Source} */
COMPOUND_EYES,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Insomnia_(ability) | Source} */
INSOMNIA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Color_Change_(ability) | Source} */
COLOR_CHANGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Immunity_(ability) | Source} */
IMMUNITY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flash_Fire_(ability) | Source} */
FLASH_FIRE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shield_Dust_(ability) | Source} */
SHIELD_DUST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Own_Tempo_(ability) | Source} */
OWN_TEMPO,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Suction_Cups_(ability) | Source} */
SUCTION_CUPS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Intimidate_(ability) | Source} */
INTIMIDATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shadow_Tag_(ability) | Source} */
SHADOW_TAG,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rough_Skin_(ability) | Source} */
ROUGH_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wonder_Guard_(ability) | Source} */
WONDER_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Levitate_(ability) | Source} */
LEVITATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Effect_Spore_(ability) | Source} */
EFFECT_SPORE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Synchronize_(ability) | Source} */
SYNCHRONIZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Clear_Body_(ability) | Source} */
CLEAR_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Natural_Cure_(ability) | Source} */
NATURAL_CURE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Lightning_Rod_(ability) | Source} */
LIGHTNING_ROD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Serene_Grace_(ability) | Source} */
SERENE_GRACE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Swift_Swim_(ability) | Source} */
SWIFT_SWIM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Chlorophyll_(ability) | Source} */
CHLOROPHYLL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Illuminate_(ability) | Source} */
ILLUMINATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Trace_(ability) | Source} */
TRACE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Huge_Power_(ability) | Source} */
HUGE_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Point_(ability) | Source} */
POISON_POINT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Inner_Focus_(ability) | Source} */
INNER_FOCUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magma_Armor_(ability) | Source} */
MAGMA_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Veil_(ability) | Source} */
WATER_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magnet_Pull_(ability) | Source} */
MAGNET_PULL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Soundproof_(ability) | Source} */
SOUNDPROOF,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rain_Dish_(ability) | Source} */
RAIN_DISH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Stream_(ability) | Source} */
SAND_STREAM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pressure_(ability) | Source} */
PRESSURE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Thick_Fat_(ability) | Source} */
THICK_FAT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Early_Bird_(ability) | Source} */
EARLY_BIRD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flame_Body_(ability) | Source} */
FLAME_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Run_Away_(ability) | Source} */
RUN_AWAY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Keen_Eye_(ability) | Source} */
KEEN_EYE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hyper_Cutter_(ability) | Source} */
HYPER_CUTTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pickup_(ability) | Source} */
PICKUP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Truant_(ability) | Source} */
TRUANT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hustle_(ability) | Source} */
HUSTLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cute_Charm_(ability) | Source} */
CUTE_CHARM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Plus_(ability) | Source} */
PLUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Minus_(ability) | Source} */
MINUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Forecast_(ability) | Source} */
FORECAST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sticky_Hold_(ability) | Source} */
STICKY_HOLD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shed_Skin_(ability) | Source} */
SHED_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Guts_(ability) | Source} */
GUTS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Marvel_Scale_(ability) | Source} */
MARVEL_SCALE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Liquid_Ooze_(ability) | Source} */
LIQUID_OOZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Overgrow_(ability) | Source} */
OVERGROW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Blaze_(ability) | Source} */
BLAZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Torrent_(ability) | Source} */
TORRENT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Swarm_(ability) | Source} */
SWARM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rock_Head_(ability) | Source} */
ROCK_HEAD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Drought_(ability) | Source} */
DROUGHT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Arena_Trap_(ability) | Source} */
ARENA_TRAP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Vital_Spirit_(ability) | Source} */
VITAL_SPIRIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/White_Smoke_(ability) | Source} */
WHITE_SMOKE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pure_Power_(ability) | Source} */
PURE_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shell_Armor_(ability) | Source} */
SHELL_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Air_Lock_(ability) | Source} */
AIR_LOCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tangled_Feet_(ability) | Source} */
TANGLED_FEET,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Motor_Drive_(ability) | Source} */
MOTOR_DRIVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rivalry_(ability) | Source} */
RIVALRY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steadfast_(ability) | Source} */
STEADFAST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Snow_Cloak_(ability) | Source} */
SNOW_CLOAK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gluttony_(ability) | Source} */
GLUTTONY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Anger_Point_(ability) | Source} */
ANGER_POINT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unburden_(ability) | Source} */
UNBURDEN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Heatproof_(ability) | Source} */
HEATPROOF,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Simple_(ability) | Source} */
SIMPLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dry_Skin_(ability) | Source} */
DRY_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Download_(ability) | Source} */
DOWNLOAD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Iron_Fist_(ability) | Source} */
IRON_FIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Heal_(ability) | Source} */
POISON_HEAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Adaptability_(ability) | Source} */
ADAPTABILITY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Skill_Link_(ability) | Source} */
SKILL_LINK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hydration_(ability) | Source} */
HYDRATION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Solar_Power_(ability) | Source} */
SOLAR_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Quick_Feet_(ability) | Source} */
QUICK_FEET,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Normalize_(ability) | Source} */
NORMALIZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sniper_(ability) | Source} */
SNIPER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magic_Guard_(ability) | Source} */
MAGIC_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/No_Guard_(ability) | Source} */
NO_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stall_(ability) | Source} */
STALL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Technician_(ability) | Source} */
TECHNICIAN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Leaf_Guard_(ability) | Source} */
LEAF_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Klutz_(ability) | Source} */
KLUTZ,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mold_Breaker_(ability) | Source} */
MOLD_BREAKER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Super_Luck_(ability) | Source} */
SUPER_LUCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aftermath_(ability) | Source} */
AFTERMATH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Anticipation_(ability) | Source} */
ANTICIPATION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Forewarn_(ability) | Source} */
FOREWARN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unaware_(ability) | Source} */
UNAWARE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tinted_Lens_(ability) | Source} */
TINTED_LENS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Filter_(ability) | Source} */
FILTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Slow_Start_(ability) | Source} */
SLOW_START,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Scrappy_(ability) | Source} */
SCRAPPY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Storm_Drain_(ability) | Source} */
STORM_DRAIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ice_Body_(ability) | Source} */
ICE_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Solid_Rock_(ability) | Source} */
SOLID_ROCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Snow_Warning_(ability) | Source} */
SNOW_WARNING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Honey_Gather_(ability) | Source} */
HONEY_GATHER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Frisk_(ability) | Source} */
FRISK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Reckless_(ability) | Source} */
RECKLESS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Multitype_(ability) | Source} */
MULTITYPE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flower_Gift_(ability) | Source} */
FLOWER_GIFT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Bad_Dreams_(ability) | Source} */
BAD_DREAMS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pickpocket_(ability) | Source} */
PICKPOCKET,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sheer_Force_(ability) | Source} */
SHEER_FORCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Contrary_(ability) | Source} */
CONTRARY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unnerve_(ability) | Source} */
UNNERVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Defiant_(ability) | Source} */
DEFIANT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Defeatist_(ability) | Source} */
DEFEATIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cursed_Body_(ability) | Source} */
CURSED_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Healer_(ability) | Source} */
HEALER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Friend_Guard_(ability) | Source} */
FRIEND_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Weak_Armor_(ability) | Source} */
WEAK_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Heavy_Metal_(ability) | Source} */
HEAVY_METAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Light_Metal_(ability) | Source} */
LIGHT_METAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Multiscale_(ability) | Source} */
MULTISCALE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Boost_(ability) | Source} */
TOXIC_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flare_Boost_(ability) | Source} */
FLARE_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Harvest_(ability) | Source} */
HARVEST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Telepathy_(ability) | Source} */
TELEPATHY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Moody_(ability) | Source} */
MOODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Overcoat_(ability) | Source} */
OVERCOAT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Touch_(ability) | Source} */
POISON_TOUCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Regenerator_(ability) | Source} */
REGENERATOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Big_Pecks_(ability) | Source} */
BIG_PECKS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Rush_(ability) | Source} */
SAND_RUSH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wonder_Skin_(ability) | Source} */
WONDER_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Analytic_(ability) | Source} */
ANALYTIC,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Illusion_(ability) | Source} */
ILLUSION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Imposter_(ability) | Source} */
IMPOSTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Infiltrator_(ability) | Source} */
INFILTRATOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mummy_(ability) | Source} */
MUMMY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Moxie_(ability) | Source} */
MOXIE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Justified_(ability) | Source} */
JUSTIFIED,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rattled_(ability) | Source} */
RATTLED,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magic_Bounce_(ability) | Source} */
MAGIC_BOUNCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sap_Sipper_(ability) | Source} */
SAP_SIPPER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Prankster_(ability) | Source} */
PRANKSTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Force_(ability) | Source} */
SAND_FORCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Iron_Barbs_(ability) | Source} */
IRON_BARBS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Zen_Mode_(ability) | Source} */
ZEN_MODE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Victory_Star_(ability) | Source} */
VICTORY_STAR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Turboblaze_(ability) | Source} */
TURBOBLAZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Teravolt_(ability) | Source} */
TERAVOLT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aroma_Veil_(ability) | Source} */
AROMA_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flower_Veil_(ability) | Source} */
FLOWER_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cheek_Pouch_(ability) | Source} */
CHEEK_POUCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Protean_(ability) | Source} */
PROTEAN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Fur_Coat_(ability) | Source} */
FUR_COAT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magician_(ability) | Source} */
MAGICIAN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Bulletproof_(ability) | Source} */
BULLETPROOF,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Competitive_(ability) | Source} */
COMPETITIVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Strong_Jaw_(ability) | Source} */
STRONG_JAW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Refrigerate_(ability) | Source} */
REFRIGERATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sweet_Veil_(ability) | Source} */
SWEET_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stance_Change_(ability) | Source} */
STANCE_CHANGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gale_Wings_(ability) | Source} */
GALE_WINGS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mega_Launcher_(ability) | Source} */
MEGA_LAUNCHER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Grass_Pelt_(ability) | Source} */
GRASS_PELT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Symbiosis_(ability) | Source} */
SYMBIOSIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tough_Claws_(ability) | Source} */
TOUGH_CLAWS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pixilate_(ability) | Source} */
PIXILATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gooey_(ability) | Source} */
GOOEY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aerilate_(ability) | Source} */
AERILATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Parental_Bond_(ability) | Source} */
PARENTAL_BOND,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dark_Aura_(ability) | Source} */
DARK_AURA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Fairy_Aura_(ability) | Source} */
FAIRY_AURA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aura_Break_(ability) | Source} */
AURA_BREAK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Primordial_Sea_(ability) | Source} */
PRIMORDIAL_SEA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Desolate_Land_(ability) | Source} */
DESOLATE_LAND,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Delta_Stream_(ability) | Source} */
DELTA_STREAM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stamina_(ability) | Source} */
STAMINA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wimp_Out_(ability) | Source} */
WIMP_OUT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Emergency_Exit_(ability) | Source} */
EMERGENCY_EXIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Compaction_(ability) | Source} */
WATER_COMPACTION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Merciless_(ability) | Source} */
MERCILESS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shields_Down_(ability) | Source} */
SHIELDS_DOWN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stakeout_(ability) | Source} */
STAKEOUT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Bubble_(ability) | Source} */
WATER_BUBBLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steelworker_(ability) | Source} */
STEELWORKER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Berserk_(ability) | Source} */
BERSERK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Slush_Rush_(ability) | Source} */
SLUSH_RUSH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Long_Reach_(ability) | Source} */
LONG_REACH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Liquid_Voice_(ability) | Source} */
LIQUID_VOICE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Triage_(ability) | Source} */
TRIAGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Galvanize_(ability) | Source} */
GALVANIZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Surge_Surfer_(ability) | Source} */
SURGE_SURFER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Schooling_(ability) | Source} */
SCHOOLING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Disguise_(ability) | Source} */
DISGUISE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Battle_Bond_(ability) | Source} */
BATTLE_BOND,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Power_Construct_(ability) | Source} */
POWER_CONSTRUCT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Corrosion_(ability) | Source} */
CORROSION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Comatose_(ability) | Source} */
COMATOSE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Queenly_Majesty_(ability) | Source} */
QUEENLY_MAJESTY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Innards_Out_(ability) | Source} */
INNARDS_OUT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dancer_(ability) | Source} */
DANCER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Battery_(ability) | Source} */
BATTERY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Fluffy_(ability) | Source} */
FLUFFY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dazzling_(ability) | Source} */
DAZZLING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Soul_Heart_(ability) | Source} */
SOUL_HEART,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tangling_Hair_(ability) | Source} */
TANGLING_HAIR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Receiver_(ability) | Source} */
RECEIVER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Power_Of_Alchemy_(ability) | Source} */
POWER_OF_ALCHEMY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Beast_Boost_(ability) | Source} */
BEAST_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rks_System_(ability) | Source} */
RKS_SYSTEM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Electric_Surge_(ability) | Source} */
ELECTRIC_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Psychic_Surge_(ability) | Source} */
PSYCHIC_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Misty_Surge_(ability) | Source} */
MISTY_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Grassy_Surge_(ability) | Source} */
GRASSY_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Full_Metal_Body_(ability) | Source} */
FULL_METAL_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shadow_Shield_(ability) | Source} */
SHADOW_SHIELD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Prism_Armor_(ability) | Source} */
PRISM_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Neuroforce_(ability) | Source} */
NEUROFORCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Intrepid_Sword_(ability) | Source} */
INTREPID_SWORD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dauntless_Shield_(ability) | Source} */
DAUNTLESS_SHIELD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Libero_(ability) | Source} */
LIBERO,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ball_Fetch_(ability) | Source} */
BALL_FETCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cotton_Down_(ability) | Source} */
COTTON_DOWN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Propeller_Tail_(ability) | Source} */
PROPELLER_TAIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mirror_Armor_(ability) | Source} */
MIRROR_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gulp_Missile_(ability) | Source} */
GULP_MISSILE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stalwart_(ability) | Source} */
STALWART,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steam_Engine_(ability) | Source} */
STEAM_ENGINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Punk_Rock_(ability) | Source} */
PUNK_ROCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Spit_(ability) | Source} */
SAND_SPIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ice_Scales_(ability) | Source} */
ICE_SCALES,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ripen_(ability) | Source} */
RIPEN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ice_Face_(ability) | Source} */
ICE_FACE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Power_Spot_(ability) | Source} */
POWER_SPOT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mimicry_(ability) | Source} */
MIMICRY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Screen_Cleaner_(ability) | Source} */
SCREEN_CLEANER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steely_Spirit_(ability) | Source} */
STEELY_SPIRIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Perish_Body_(ability) | Source} */
PERISH_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wandering_Spirit_(ability) | Source} */
WANDERING_SPIRIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gorilla_Tactics_(ability) | Source} */
GORILLA_TACTICS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Neutralizing_Gas_(ability) | Source} */
NEUTRALIZING_GAS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pastel_Veil_(ability) | Source} */
PASTEL_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hunger_Switch_(ability) | Source} */
HUNGER_SWITCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Quick_Draw_(ability) | Source} */
QUICK_DRAW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unseen_Fist_(ability) | Source} */
UNSEEN_FIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Curious_Medicine_(ability) | Source} */
CURIOUS_MEDICINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Transistor_(ability) | Source} */
TRANSISTOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dragons_Maw_(ability) | Source} */
DRAGONS_MAW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Chilling_Neigh_(ability) | Source} */
CHILLING_NEIGH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Grim_Neigh_(ability) | Source} */
GRIM_NEIGH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/As_One_Glastrier_(ability) | Source} */
AS_ONE_GLASTRIER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/As_One_Spectrier_(ability) | Source} */
AS_ONE_SPECTRIER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Lingering_Aroma_(ability) | Source} */
LINGERING_AROMA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Seed_Sower_(ability) | Source} */
SEED_SOWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Thermal_Exchange_(ability) | Source} */
THERMAL_EXCHANGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Anger_Shell_(ability) | Source} */
ANGER_SHELL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Purifying_Salt_(ability) | Source} */
PURIFYING_SALT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Well_Baked_Body_(ability) | Source} */
WELL_BAKED_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wind_Rider_(ability) | Source} */
WIND_RIDER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Guard_Dog_(ability) | Source} */
GUARD_DOG,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rocky_Payload_(ability) | Source} */
ROCKY_PAYLOAD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wind_Power_(ability) | Source} */
WIND_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Zero_To_Hero_(ability) | Source} */
ZERO_TO_HERO,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Commander_(ability) | Source} */
COMMANDER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Electromorphosis_(ability) | Source} */
ELECTROMORPHOSIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Protosynthesis_(ability) | Source} */
PROTOSYNTHESIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Quark_Drive_(ability) | Source} */
QUARK_DRIVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Good_As_Gold_(ability) | Source} */
GOOD_AS_GOLD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Vessel_Of_Ruin_(ability) | Source} */
VESSEL_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sword_Of_Ruin_(ability) | Source} */
SWORD_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tablets_Of_Ruin_(ability) | Source} */
TABLETS_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Beads_Of_Ruin_(ability) | Source} */
BEADS_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Orichalcum_Pulse_(ability) | Source} */
ORICHALCUM_PULSE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hadron_Engine_(ability) | Source} */
HADRON_ENGINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Opportunist_(ability) | Source} */
OPPORTUNIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cud_Chew_(ability) | Source} */
CUD_CHEW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sharpness_(ability) | Source} */
SHARPNESS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Supreme_Overlord_(ability) | Source} */
SUPREME_OVERLORD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Costar_(ability) | Source} */
COSTAR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Debris_(ability) | Source} */
TOXIC_DEBRIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Armor_Tail_(ability) | Source} */
ARMOR_TAIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Earth_Eater_(ability) | Source} */
EARTH_EATER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mycelium_Might_(ability) | Source} */
MYCELIUM_MIGHT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Minds_Eye_(ability) | Source} */
MINDS_EYE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Supersweet_Syrup_(ability) | Source} */
SUPERSWEET_SYRUP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hospitality_(ability) | Source} */
HOSPITALITY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Chain_(ability) | Source} */
TOXIC_CHAIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Teal_(ability) | Source} */
EMBODY_ASPECT_TEAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Wellspring_(ability) | Source} */
EMBODY_ASPECT_WELLSPRING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Hearthflame_(ability) | Source} */
EMBODY_ASPECT_HEARTHFLAME,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Cornerstone_(ability) | Source} */
EMBODY_ASPECT_CORNERSTONE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shift_(ability) | Source} */
TERA_SHIFT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shell_(ability) | Source} */
TERA_SHELL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Teraform_Zero_(ability) | Source} */
TERAFORM_ZERO,
POISON_PUPPETEER
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Puppeteer_(ability) | Source} */
POISON_PUPPETEER,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -54,22 +54,28 @@ export enum MoveTarget {
}
export enum MoveFlags {
MAKES_CONTACT = 1,
IGNORE_PROTECT = 2,
IGNORE_VIRTUAL = 4,
SOUND_BASED = 8,
HIDE_USER = 16,
HIDE_TARGET = 32,
BITING_MOVE = 64,
PULSE_MOVE = 128,
PUNCHING_MOVE = 256,
SLICING_MOVE = 512,
BALLBOMB_MOVE = 1024,
POWDER_MOVE = 2048,
DANCE_MOVE = 4096,
WIND_MOVE = 8192,
TRIAGE_MOVE = 16384,
IGNORE_ABILITIES = 32768
NONE = 0,
MAKES_CONTACT = 1 << 0,
IGNORE_PROTECT = 1 << 1,
IGNORE_VIRTUAL = 1 << 2,
SOUND_BASED = 1 << 3,
HIDE_USER = 1 << 4,
HIDE_TARGET = 1 << 5,
BITING_MOVE = 1 << 6,
PULSE_MOVE = 1 << 7,
PUNCHING_MOVE = 1 << 8,
SLICING_MOVE = 1 << 9,
/**
* Indicates a move should be affected by {@link Abilities.RECKLESS}
* @see {@link Move.recklessMove()}
*/
RECKLESS_MOVE = 1 << 10,
BALLBOMB_MOVE = 1 << 11,
POWDER_MOVE = 1 << 12,
DANCE_MOVE = 1 << 13,
WIND_MOVE = 1 << 14,
TRIAGE_MOVE = 1 << 15,
IGNORE_ABILITIES = 1 << 16,
}
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
@ -269,6 +275,17 @@ export default class Move implements Localizable {
return this;
}
/**
* Sets the {@link MoveFlags.RECKLESS_MOVE} flag for the calling Move
* @see {@link Abilities.RECKLESS}
* @param {boolean} recklessMove The value to set the flag to
* @returns {Move} The {@link Move} that called this function
*/
recklessMove(recklessMove?: boolean): this {
this.setFlag(MoveFlags.RECKLESS_MOVE, recklessMove);
return this;
}
ballBombMove(ballBombMove?: boolean): this {
this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove);
return this;
@ -367,7 +384,7 @@ export class AttackMove extends Move {
let attackScore = 0;
const effectiveness = target.getAttackTypeEffectiveness(this.type);
const effectiveness = target.getAttackTypeEffectiveness(this.type, user);
attackScore = Math.pow(effectiveness - 1, 2) * effectiveness < 1 ? -2 : 2;
if (attackScore) {
if (this.category === MoveCategory.PHYSICAL) {
@ -738,7 +755,7 @@ export class SacrificialAttr extends MoveEffectAttr {
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
if (user.isBoss())
return -20;
return Math.ceil(((1 - user.getHpRatio()) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type) - 0.5));
return Math.ceil(((1 - user.getHpRatio()) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type, user) - 0.5));
}
}
@ -776,7 +793,7 @@ export class HalfSacrificialAttr extends MoveEffectAttr {
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
if (user.isBoss())
return -10;
return Math.ceil(((1 - user.getHpRatio()/2) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type) - 0.5));
return Math.ceil(((1 - user.getHpRatio()/2) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type, user) - 0.5));
}
}
@ -1544,6 +1561,29 @@ export class StatChangeAttr extends MoveEffectAttr {
}
}
export class PostVictoryStatChangeAttr extends MoveAttr {
private stats: BattleStat[];
private levels: integer;
private condition: MoveConditionFunc;
private showMessage: boolean;
constructor(stats: BattleStat | BattleStat[], levels: integer, selfTarget?: boolean, condition?: MoveConditionFunc, showMessage: boolean = true, firstHitOnly: boolean = false) {
super();
this.stats = typeof(stats) === 'number'
? [ stats as BattleStat ]
: stats as BattleStat[];
this.levels = levels;
this.condition = condition || null;
this.showMessage = showMessage;
}
applyPostVictory(user: Pokemon, target: Pokemon, move: Move): void {
if(this.condition && !this.condition(user, target, move))
return false;
const statChangeAttr = new StatChangeAttr(this.stats, this.levels, this.showMessage);
statChangeAttr.apply(user, target, move);
}
}
export class AcupressureStatChangeAttr extends MoveEffectAttr {
constructor() {
super();
@ -1558,7 +1598,7 @@ export class AcupressureStatChangeAttr extends MoveEffectAttr {
return true;
}
return false;
}
}
}
export class GrowthStatChangeAttr extends StatChangeAttr {
@ -2440,6 +2480,27 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
}
}
export class MatchUserTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const type = (args[0] as Utils.IntegerHolder);
const userTypes = user.getTypes(true);
if(userTypes.includes(Type.STELLAR)) { // will not change to stellar type
const nonTeraTypes = user.getTypes();
type.value = nonTeraTypes[0];
return true;
}
else if (userTypes.length > 0) {
type.value = userTypes[0];
return true;
}
else
return false;
}
}
export class VariableMoveTypeMultiplierAttr extends MoveAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
return false;
@ -2476,7 +2537,7 @@ export class WaterSuperEffectTypeMultiplierAttr extends VariableMoveTypeMultipli
export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const multiplier = args[0] as Utils.NumberHolder;
multiplier.value *= target.getAttackTypeEffectiveness(Type.FLYING);
multiplier.value *= target.getAttackTypeEffectiveness(Type.FLYING, user);
return true;
}
}
@ -2940,6 +3001,42 @@ export class AddArenaTrapTagAttr extends AddArenaTagAttr {
}
}
export class RemoveArenaTrapAttr extends MoveEffectAttr {
private targetBothSides: boolean;
constructor(targetBothSides: boolean = false) {
super(true, MoveEffectTrigger.PRE_APPLY);
this.targetBothSides = targetBothSides;
}
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args))
return false;
if(this.targetBothSides){
user.scene.arena.removeTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.PLAYER);
user.scene.arena.removeTagOnSide(ArenaTagType.TOXIC_SPIKES, ArenaTagSide.PLAYER);
user.scene.arena.removeTagOnSide(ArenaTagType.STEALTH_ROCK, ArenaTagSide.PLAYER);
user.scene.arena.removeTagOnSide(ArenaTagType.STICKY_WEB, ArenaTagSide.PLAYER);
user.scene.arena.removeTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY);
user.scene.arena.removeTagOnSide(ArenaTagType.TOXIC_SPIKES, ArenaTagSide.ENEMY);
user.scene.arena.removeTagOnSide(ArenaTagType.STEALTH_ROCK, ArenaTagSide.ENEMY);
user.scene.arena.removeTagOnSide(ArenaTagType.STICKY_WEB, ArenaTagSide.ENEMY);
}
else {
user.scene.arena.removeTagOnSide(ArenaTagType.SPIKES, target.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER);
user.scene.arena.removeTagOnSide(ArenaTagType.TOXIC_SPIKES, target.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER);
user.scene.arena.removeTagOnSide(ArenaTagType.STEALTH_ROCK, target.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER);
user.scene.arena.removeTagOnSide(ArenaTagType.STICKY_WEB, target.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER);
}
return true;
}
}
export class RemoveScreensAttr extends MoveEffectAttr {
private targetBothSides: boolean;
@ -4016,7 +4113,8 @@ export function initMoves() {
new AttackMove(Moves.JUMP_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 95, 10, -1, 0, 1)
.attr(MissEffectAttr, crashDamageFunc)
.attr(NoEffectAttr, crashDamageFunc)
.condition(failOnGravityCondition),
.condition(failOnGravityCondition)
.recklessMove(),
new AttackMove(Moves.ROLLING_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 85, 15, 30, 0, 1)
.attr(FlinchAttr),
new StatusMove(Moves.SAND_ATTACK, Type.GROUND, 100, 15, -1, 0, 1)
@ -4035,13 +4133,15 @@ export function initMoves() {
new AttackMove(Moves.WRAP, Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, 100, 0, 1)
.attr(TrapAttr, BattlerTagType.WRAP),
new AttackMove(Moves.TAKE_DOWN, Type.NORMAL, MoveCategory.PHYSICAL, 90, 85, 20, -1, 0, 1)
.attr(RecoilAttr),
.attr(RecoilAttr)
.recklessMove(),
new AttackMove(Moves.THRASH, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 1)
.attr(FrenzyAttr)
.attr(MissEffectAttr, frenzyMissFunc)
.target(MoveTarget.RANDOM_NEAR_ENEMY),
new AttackMove(Moves.DOUBLE_EDGE, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 1)
.attr(RecoilAttr, false, 0.33),
.attr(RecoilAttr, false, 0.33)
.recklessMove(),
new StatusMove(Moves.TAIL_WHIP, Type.NORMAL, 100, 30, -1, 0, 1)
.attr(StatChangeAttr, BattleStat.DEF, -1)
.target(MoveTarget.ALL_NEAR_ENEMIES),
@ -4113,7 +4213,8 @@ export function initMoves() {
new AttackMove(Moves.PECK, Type.FLYING, MoveCategory.PHYSICAL, 35, 100, 35, -1, 0, 1),
new AttackMove(Moves.DRILL_PECK, Type.FLYING, MoveCategory.PHYSICAL, 80, 100, 20, -1, 0, 1),
new AttackMove(Moves.SUBMISSION, Type.FIGHTING, MoveCategory.PHYSICAL, 80, 80, 20, -1, 0, 1)
.attr(RecoilAttr),
.attr(RecoilAttr)
.recklessMove(),
new AttackMove(Moves.LOW_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, 0, 1)
.attr(WeightPowerAttr)
.condition(failOnMaxCondition),
@ -4301,7 +4402,8 @@ export function initMoves() {
new AttackMove(Moves.HIGH_JUMP_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 130, 90, 10, -1, 0, 1)
.attr(MissEffectAttr, crashDamageFunc)
.attr(NoEffectAttr, crashDamageFunc)
.condition(failOnGravityCondition),
.condition(failOnGravityCondition)
.recklessMove(),
new StatusMove(Moves.GLARE, Type.NORMAL, 100, 30, -1, 0, 1)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
new AttackMove(Moves.DREAM_EATER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 15, -1, 0, 1)
@ -4581,7 +4683,7 @@ export function initMoves() {
BattlerTagType.SEEDED,
BattlerTagType.INFESTATION
], true)
.partial(),
.attr(RemoveArenaTrapAttr),
new StatusMove(Moves.SWEET_SCENT, Type.NORMAL, 100, 20, -1, 0, 2)
.attr(StatChangeAttr, BattleStat.EVA, -1)
.target(MoveTarget.ALL_NEAR_ENEMIES),
@ -4886,7 +4988,8 @@ export function initMoves() {
.attr(StealHeldItemChanceAttr, 0.3),
new AttackMove(Moves.VOLT_TACKLE, Type.ELECTRIC, MoveCategory.PHYSICAL, 120, 100, 15, 10, 0, 3)
.attr(RecoilAttr, false, 0.33)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
.recklessMove(),
new AttackMove(Moves.MAGICAL_LEAF, Type.GRASS, MoveCategory.SPECIAL, 60, -1, 20, -1, 0, 3),
new StatusMove(Moves.WATER_SPORT, Type.WATER, -1, 15, -1, 0, 3)
.attr(AddArenaTagAttr, ArenaTagType.WATER_SPORT, 5)
@ -5029,7 +5132,8 @@ export function initMoves() {
.attr(RecoilAttr, false, 0.33)
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
.attr(StatusEffectAttr, StatusEffect.BURN)
.condition(failOnGravityCondition),
.condition(failOnGravityCondition)
.recklessMove(),
new AttackMove(Moves.FORCE_PALM, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, 30, 0, 4)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
new AttackMove(Moves.AURA_SPHERE, Type.FIGHTING, MoveCategory.SPECIAL, 80, -1, 20, -1, 0, 4)
@ -5074,7 +5178,8 @@ export function initMoves() {
.attr(StatChangeAttr, BattleStat.SPDEF, -1)
.ballBombMove(),
new AttackMove(Moves.BRAVE_BIRD, Type.FLYING, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 4)
.attr(RecoilAttr, false, 0.33),
.attr(RecoilAttr, false, 0.33)
.recklessMove(),
new AttackMove(Moves.EARTH_POWER, Type.GROUND, MoveCategory.SPECIAL, 90, 100, 10, 10, 0, 4)
.attr(StatChangeAttr, BattleStat.SPDEF, -1),
new StatusMove(Moves.SWITCHEROO, Type.DARK, 100, 10, -1, 0, 4)
@ -5123,7 +5228,8 @@ export function initMoves() {
.attr(StatChangeAttr, BattleStat.EVA, -1)
.attr(ClearWeatherAttr, WeatherType.FOG)
.attr(ClearTerrainAttr)
.attr(RemoveScreensAttr, true),
.attr(RemoveScreensAttr, false)
.attr(RemoveArenaTrapAttr, true),
new StatusMove(Moves.TRICK_ROOM, Type.PSYCHIC, -1, 5, -1, -7, 4)
.attr(AddArenaTagAttr, ArenaTagType.TRICK_ROOM, 5)
.ignoresProtect()
@ -5179,7 +5285,8 @@ export function initMoves() {
new AttackMove(Moves.CHARGE_BEAM, Type.ELECTRIC, MoveCategory.SPECIAL, 50, 90, 10, 70, 0, 4)
.attr(StatChangeAttr, BattleStat.SPATK, 1, true),
new AttackMove(Moves.WOOD_HAMMER, Type.GRASS, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 4)
.attr(RecoilAttr, false, 0.33),
.attr(RecoilAttr, false, 0.33)
.recklessMove(),
new AttackMove(Moves.AQUA_JET, Type.WATER, MoveCategory.PHYSICAL, 40, 100, 20, -1, 1, 4),
new AttackMove(Moves.ATTACK_ORDER, Type.BUG, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 4)
.attr(HighCritAttr)
@ -5190,7 +5297,8 @@ export function initMoves() {
.attr(HealAttr, 0.5)
.triageMove(),
new AttackMove(Moves.HEAD_SMASH, Type.ROCK, MoveCategory.PHYSICAL, 150, 80, 5, -1, 0, 4)
.attr(RecoilAttr, false, 0.5),
.attr(RecoilAttr, false, 0.5)
.recklessMove(),
new AttackMove(Moves.DOUBLE_HIT, Type.NORMAL, MoveCategory.PHYSICAL, 35, 90, 10, -1, 0, 4)
.attr(MultiHitAttr, MultiHitType._2),
new AttackMove(Moves.ROAR_OF_TIME, Type.DRAGON, MoveCategory.SPECIAL, 150, 90, 5, -1, 0, 4)
@ -5378,7 +5486,8 @@ export function initMoves() {
.attr(StatChangeAttr, BattleStat.SPD, -1)
.target(MoveTarget.ALL_NEAR_ENEMIES),
new AttackMove(Moves.WILD_CHARGE, Type.ELECTRIC, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 5)
.attr(RecoilAttr),
.attr(RecoilAttr)
.recklessMove(),
new AttackMove(Moves.DRILL_RUN, Type.GROUND, MoveCategory.PHYSICAL, 80, 95, 10, -1, 0, 5)
.attr(HighCritAttr),
new AttackMove(Moves.DUAL_CHOP, Type.DRAGON, MoveCategory.PHYSICAL, 40, 90, 15, -1, 0, 5)
@ -5415,7 +5524,8 @@ export function initMoves() {
.attr(HitsTagAttr, BattlerTagType.FLYING, false)
.windMove(),
new AttackMove(Moves.HEAD_CHARGE, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 5)
.attr(RecoilAttr),
.attr(RecoilAttr)
.recklessMove(),
new AttackMove(Moves.GEAR_GRIND, Type.STEEL, MoveCategory.PHYSICAL, 50, 85, 15, -1, 0, 5)
.attr(MultiHitAttr, MultiHitType._2),
new AttackMove(Moves.SEARING_SHOT, Type.FIRE, MoveCategory.SPECIAL, 100, 100, 5, 30, 0, 5)
@ -5478,7 +5588,7 @@ export function initMoves() {
.attr(AddArenaTrapTagAttr, ArenaTagType.STICKY_WEB)
.target(MoveTarget.ENEMY_SIDE),
new AttackMove(Moves.FELL_STINGER, Type.BUG, MoveCategory.PHYSICAL, 50, 100, 25, -1, 0, 6)
.partial(),
.attr(PostVictoryStatChangeAttr, BattleStat.ATK, 3, true ),
new AttackMove(Moves.PHANTOM_FORCE, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
.attr(ChargeAttr, ChargeAnim.PHANTOM_FORCE_CHARGING, 'vanished\ninstantly!', BattlerTagType.HIDDEN)
.ignoresProtect()
@ -5629,7 +5739,8 @@ export function initMoves() {
.makesContact(false)
.target(MoveTarget.ALL_NEAR_ENEMIES),
new AttackMove(Moves.LIGHT_OF_RUIN, Type.FAIRY, MoveCategory.SPECIAL, 140, 90, 5, -1, 0, 6)
.attr(RecoilAttr, false, 0.5),
.attr(RecoilAttr, false, 0.5)
.recklessMove(),
new AttackMove(Moves.ORIGIN_PULSE, Type.WATER, MoveCategory.SPECIAL, 110, 85, 10, -1, 0, 6)
.pulseMove()
.target(MoveTarget.ALL_NEAR_ENEMIES),
@ -5796,7 +5907,7 @@ export function initMoves() {
.unimplemented(),
new AttackMove(Moves.REVELATION_DANCE, Type.NORMAL, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 7)
.danceMove()
.partial(),
.attr(MatchUserTypeAttr),
new AttackMove(Moves.CORE_ENFORCER, Type.DRAGON, MoveCategory.SPECIAL, 100, 100, 10, -1, 0, 7)
.target(MoveTarget.ALL_NEAR_ENEMIES)
.partial(),
@ -5920,7 +6031,8 @@ export function initMoves() {
.attr(FriendshipPowerAttr),
new AttackMove(Moves.BOUNCY_BUBBLE, Type.WATER, MoveCategory.SPECIAL, 60, 100, 20, -1, 0, 7)
.attr(HitHealAttr, 1.0)
.triageMove(),
.triageMove()
.target(MoveTarget.ALL_NEAR_ENEMIES),
new AttackMove(Moves.BUZZY_BUZZ, Type.ELECTRIC, MoveCategory.SPECIAL, 60, 100, 20, 100, 0, 7)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
new AttackMove(Moves.SIZZLY_SLIDE, Type.FIRE, MoveCategory.PHYSICAL, 60, 100, 20, 100, 0, 7)
@ -6182,7 +6294,8 @@ export function initMoves() {
new AttackMove(Moves.THUNDEROUS_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 90, 100, 10, 100, 0, 8)
.attr(StatChangeAttr, BattleStat.DEF, -1),
new AttackMove(Moves.GLACIAL_LANCE, Type.ICE, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 8)
.target(MoveTarget.ALL_NEAR_ENEMIES),
.target(MoveTarget.ALL_NEAR_ENEMIES)
.makesContact(false),
new AttackMove(Moves.ASTRAL_BARRAGE, Type.GHOST, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 8)
.target(MoveTarget.ALL_NEAR_ENEMIES),
new AttackMove(Moves.EERIE_SPELL, Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 5, 100, 0, 8)
@ -6208,7 +6321,8 @@ export function initMoves() {
.attr(MissEffectAttr, frenzyMissFunc)
.target(MoveTarget.RANDOM_NEAR_ENEMY),
new AttackMove(Moves.WAVE_CRASH, Type.WATER, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 8)
.attr(RecoilAttr, false, 0.33),
.attr(RecoilAttr, false, 0.33)
.recklessMove(),
new AttackMove(Moves.CHLOROBLAST, Type.GRASS, MoveCategory.SPECIAL, 150, 95, 5, -1, 0, 8)
.attr(RecoilAttr, true, 0.5),
new AttackMove(Moves.MOUNTAIN_GALE, Type.ICE, MoveCategory.PHYSICAL, 100, 85, 10, 30, 0, 8)
@ -6372,7 +6486,8 @@ export function initMoves() {
new AttackMove(Moves.AXE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 90, 10, 30, 0, 9)
.attr(MissEffectAttr, crashDamageFunc)
.attr(NoEffectAttr, crashDamageFunc)
.attr(ConfuseAttr),
.attr(ConfuseAttr)
.recklessMove(),
new AttackMove(Moves.LAST_RESPECTS, Type.GHOST, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 9)
.attr(MovePowerMultiplierAttr, (user, target, move) => {
return user.scene.getParty().reduce((acc, pokemonInParty) => acc + (pokemonInParty.status?.effect == StatusEffect.FAINT ? 1 : 0),
@ -6422,6 +6537,7 @@ export function initMoves() {
BattlerTagType.INFESTATION
], true)
.attr(StatusEffectAttr, StatusEffect.POISON)
.attr(RemoveArenaTrapAttr)
.target(MoveTarget.ALL_NEAR_ENEMIES),
new StatusMove(Moves.DOODLE, Type.NORMAL, 100, 10, -1, 0, 9)
.attr(AbilityCopyAttr, true),
@ -6453,9 +6569,9 @@ export function initMoves() {
new AttackMove(Moves.RUINATION, Type.DARK, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 9)
.attr(TargetHalfHpDamageAttr),
new AttackMove(Moves.COLLISION_COURSE, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9)
.attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) >= 2 ? 5461/4096 : 1),
.attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2 ? 5461/4096 : 1),
new AttackMove(Moves.ELECTRO_DRIFT, Type.ELECTRIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 9)
.attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) >= 2 ? 5461/4096 : 1)
.attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2 ? 5461/4096 : 1)
.makesContact(),
new SelfStatusMove(Moves.SHED_TAIL, Type.NORMAL, -1, 10, -1, 0, 9)
.unimplemented(),
@ -6465,7 +6581,7 @@ export function initMoves() {
.target(MoveTarget.BOTH_SIDES),
new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, 100, 0, 9)
.attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPD ], 1, true)
.partial(),
.attr(RemoveArenaTrapAttr),
new StatusMove(Moves.SNOWSCAPE, Type.ICE, -1, 10, -1, 0, 9)
.attr(WeatherChangeAttr, WeatherType.SNOW)
.target(MoveTarget.BOTH_SIDES),
@ -6575,7 +6691,8 @@ export function initMoves() {
.attr(MovePowerMultiplierAttr, (user, target, move) => user.getLastXMoves(2)[1]?.result == MoveResult.MISS || user.getLastXMoves(2)[1]?.result == MoveResult.FAIL ? 2 : 1),
new AttackMove(Moves.SUPERCELL_SLAM, Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 95, 15, -1, 0, 9)
.attr(MissEffectAttr, crashDamageFunc)
.attr(NoEffectAttr, crashDamageFunc),
.attr(NoEffectAttr, crashDamageFunc)
.recklessMove(),
new AttackMove(Moves.PSYCHIC_NOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, -1, 0, 9)
.soundBased()
.partial(),

File diff suppressed because it is too large Load Diff

View File

@ -51855,7 +51855,6 @@ export const tmSpecies: TmSpecies = {
Species.MABOSSTIFF,
Species.BOMBIRDIER,
Species.WALKING_WAKE,
Species.PIKACHU,
Species.ALOLA_SANDSHREW,
Species.ALOLA_SANDSLASH,
Species.ALOLA_DIGLETT,
@ -60029,6 +60028,7 @@ export const tmSpecies: TmSpecies = {
Species.SHARPEDO,
Species.SEVIPER,
Species.SALAMENCE,
Species.METAGROSS,
Species.SHINX,
Species.LUXIO,
Species.LUXRAY,

View File

@ -543,4 +543,4 @@ export function getTypeRgb(type: Type): [ integer, integer, integer ] {
default:
return [ 0, 0, 0 ];
}
}
}

View File

@ -19,7 +19,7 @@ import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEv
import { reverseCompatibleTms, tmSpecies } from '../data/tms';
import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases';
import { BattleStat } from '../data/battle-stat';
import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags';
import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags';
import { BattlerTagType } from "../data/enums/battler-tag-type";
import { Species } from '../data/enums/species';
import { WeatherType } from '../data/weather';
@ -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 } 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 } from '../data/ability';
import { Abilities } from "#app/data/enums/abilities";
import PokemonData from '../system/pokemon-data';
import Battle, { BattlerIndex } from '../battle';
@ -43,7 +43,7 @@ import { Nature, getNatureStatMultiplier } from '../data/nature';
import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from '../data/pokemon-forms';
import { TerrainType } from '../data/terrain';
import { TrainerSlot } from '../data/trainer-config';
import { ABILITY_OVERRIDE, MOVE_OVERRIDE, MOVE_OVERRIDE_2, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_MOVE_OVERRIDE_2, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides';
import { ABILITY_OVERRIDE, MOVE_OVERRIDE, MOVE_OVERRIDE_2, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_MOVE_OVERRIDE_2, OPP_PASSIVE_ABILITY_OVERRIDE, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE, PASSIVE_ABILITY_OVERRIDE } from '../overrides';
import { BerryType } from '../data/berry';
import i18next from '../plugins/i18n';
@ -600,7 +600,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
ret >>= 1;
break;
}
const highestStatBoost = this.findTag(t => t instanceof HighestStatBoostTag && (t as HighestStatBoostTag).stat === stat) as HighestStatBoostTag;
if (highestStatBoost)
ret *= highestStatBoost.multiplier;
return Math.floor(ret);
}
@ -774,9 +778,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
types.splice(flyingIndex, 1);
}
if (!types.length)
if (!types.length) // become UNKNOWN if no types are present
types.push(Type.UNKNOWN);
if (types.length > 1 && types.includes(Type.UNKNOWN)) { // remove UNKNOWN if other types are present
const index = types.indexOf(Type.UNKNOWN);
if (index !== -1) {
types.splice(index, 1);
}
}
return types;
}
@ -800,6 +811,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
getPassiveAbility(): Ability {
if (PASSIVE_ABILITY_OVERRIDE && this.isPlayer())
return allAbilities[PASSIVE_ABILITY_OVERRIDE];
if (OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer())
return allAbilities[OPP_PASSIVE_ABILITY_OVERRIDE];
let starterSpeciesId = this.species.speciesId;
while (pokemonPrevolutions.hasOwnProperty(starterSpeciesId))
starterSpeciesId = pokemonPrevolutions[starterSpeciesId];
@ -807,6 +823,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
hasPassive(): boolean {
if ((PASSIVE_ABILITY_OVERRIDE !== Abilities.NONE && this.isPlayer()) || (OPP_PASSIVE_ABILITY_OVERRIDE !== Abilities.NONE && !this.isPlayer()))
return true;
return this.passive || this.isBoss();
}
@ -876,7 +894,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
getAttackMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier {
const typeless = !!move.getMove().getAttrs(TypelessAttr).length;
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.getMove().type));
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.getMove().type, source));
const cancelled = new Utils.BooleanHolder(false);
if (!typeless)
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true);
@ -885,11 +903,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return (!cancelled.value ? typeMultiplier.value : 0) as TypeDamageMultiplier;
}
getAttackTypeEffectiveness(moveType: Type): TypeDamageMultiplier {
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon): TypeDamageMultiplier {
if (moveType === Type.STELLAR)
return this.isTerastallized() ? 2 : 1;
const types = this.getTypes(true, true);
let multiplier = getTypeDamageMultiplier(moveType, types[0]) * (types.length > 1 ? getTypeDamageMultiplier(moveType, types[1]) : 1) * (types.length > 2 ? getTypeDamageMultiplier(moveType, types[2]) : 1) as TypeDamageMultiplier;
let multiplier = types.map(defType => {
if (source) {
const ignoreImmunity = new Utils.BooleanHolder(false);
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, moveType, defType);
if (ignoreImmunity.value)
return 1;
}
return getTypeDamageMultiplier(moveType, defType);
}).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier;
// Handle strong winds lowering effectiveness of types super effective against pure flying
if (this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && multiplier >= 2 && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2)
multiplier /= 2;
@ -900,12 +929,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const types = this.getTypes(true);
const enemyTypes = pokemon.getTypes(true, true);
const outspeed = (this.isActive(true) ? this.getBattleStat(Stat.SPD, pokemon) : this.getStat(Stat.SPD)) <= pokemon.getBattleStat(Stat.SPD, this);
let atkScore = pokemon.getAttackTypeEffectiveness(types[0]) * (outspeed ? 1.25 : 1);
let defScore = 1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[0]), 0.25);
let atkScore = pokemon.getAttackTypeEffectiveness(types[0], this) * (outspeed ? 1.25 : 1);
let defScore = 1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[0], pokemon), 0.25);
if (types.length > 1)
atkScore *= pokemon.getAttackTypeEffectiveness(types[1]);
atkScore *= pokemon.getAttackTypeEffectiveness(types[1], this);
if (enemyTypes.length > 1)
defScore *= (1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[1]), 0.25));
defScore *= (1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[1], pokemon), 0.25));
let hpDiffRatio = this.getHpRatio() + (1 - pokemon.getHpRatio());
if (outspeed)
hpDiffRatio = Math.min(hpDiffRatio * 1.5, 1);
@ -1258,7 +1287,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const cancelled = new Utils.BooleanHolder(false);
const typeless = !!move.getAttrs(TypelessAttr).length;
const typeMultiplier = new Utils.NumberHolder(!typeless && (moveCategory !== MoveCategory.STATUS || move.getAttrs(StatusMoveTypeImmunityAttr).find(attr => types.includes((attr as StatusMoveTypeImmunityAttr).immuneType)))
? this.getAttackTypeEffectiveness(type)
? this.getAttackTypeEffectiveness(type, source)
: 1);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
if (typeless)
@ -1681,18 +1710,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
});
}
cry(soundConfig?: Phaser.Types.Sound.SoundConfig): AnySound {
const cry = this.getSpeciesForm().cry(this.scene, soundConfig);
cry(soundConfig?: Phaser.Types.Sound.SoundConfig, sceneOverride?: BattleScene): AnySound {
const scene = sceneOverride || this.scene;
const cry = this.getSpeciesForm().cry(scene, soundConfig);
let duration = cry.totalDuration * 1000;
if (this.fusionSpecies) {
let fusionCry = this.getFusionSpeciesForm().cry(this.scene, soundConfig, true);
let fusionCry = this.getFusionSpeciesForm().cry(scene, soundConfig, true);
duration = Math.min(duration, fusionCry.totalDuration * 1000);
fusionCry.destroy();
this.scene.time.delayedCall(Utils.fixedInt(Math.ceil(duration * 0.4)), () => {
scene.time.delayedCall(Utils.fixedInt(Math.ceil(duration * 0.4)), () => {
try {
SoundFade.fadeOut(this.scene, cry, Utils.fixedInt(Math.ceil(duration * 0.2)));
fusionCry = this.getFusionSpeciesForm().cry(this.scene, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0) }, soundConfig));
SoundFade.fadeIn(this.scene, fusionCry, Utils.fixedInt(Math.ceil(duration * 0.2)), this.scene.masterVolume * this.scene.seVolume, 0);
SoundFade.fadeOut(scene, cry, Utils.fixedInt(Math.ceil(duration * 0.2)));
fusionCry = this.getFusionSpeciesForm().cry(scene, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0) }, soundConfig));
SoundFade.fadeIn(scene, fusionCry, Utils.fixedInt(Math.ceil(duration * 0.2)), scene.masterVolume * scene.seVolume, 0);
} catch (err) {
console.error(err);
}
@ -3106,6 +3136,7 @@ export class PokemonBattleData {
public hitCount: integer = 0;
public endured: boolean = false;
public berriesEaten: BerryType[] = [];
public abilitiesApplied: Abilities[] = [];
}
export class PokemonBattleSummonData {
@ -3168,7 +3199,7 @@ export class PokemonMove {
isUsable(pokemon: Pokemon, ignorePp?: boolean): boolean {
if (this.moveId && pokemon.summonData?.disabledMove === this.moveId)
return false;
return ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1;
return (ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1) && !this.getMove().name.endsWith(' (N)');
}
getMove(): Move {

View File

@ -31,6 +31,7 @@ export class InputsController {
// buttonLock ensures only a single movement key is firing repeated inputs
// (i.e. by holding down a button) at a time
private buttonLock: Button;
private buttonLock2: Button;
private interactions: Map<Button, Map<string, boolean>> = new Map();
private time: Time;
private player: Map<String, GamepadMapping> = new Map();
@ -87,7 +88,8 @@ export class InputsController {
}
update(): void {
for (const b of Utils.getEnumValues(Button)) {
// reversed to let the cancel button have a kinda priority on the action button
for (const b of Utils.getEnumValues(Button).reverse()) {
if (!this.interactions.hasOwnProperty(b)) continue;
if (this.repeatInputDurationJustPassed(b) && this.interactions[b].isPressed) {
this.events.emit('input_down', {
@ -243,35 +245,50 @@ export class InputsController {
* firing a repeated input - this is to prevent multiple buttons from firing repeatedly.
*/
repeatInputDurationJustPassed(button: Button): boolean {
if (this.buttonLock === null || this.buttonLock !== button) {
return false;
}
if (!this.isButtonLocked(button)) return false;
if (this.time.now - this.interactions[button].pressTime >= repeatInputDelayMillis) {
this.buttonLock = null;
return true;
}
}
setLastProcessedMovementTime(button: Button): void {
if (!this.interactions.hasOwnProperty(button)) return;
this.buttonLock = button;
this.setButtonLock(button);
this.interactions[button].pressTime = this.time.now;
this.interactions[button].isPressed = true;
}
delLastProcessedMovementTime(button: Button): void {
if (!this.interactions.hasOwnProperty(button)) return;
this.buttonLock = null;
this.releaseButtonLock(button);
this.interactions[button].pressTime = null;
this.interactions[button].isPressed = false;
}
deactivatePressedKey(): void {
this.buttonLock = null;
this.releaseButtonLock(this.buttonLock);
this.releaseButtonLock(this.buttonLock2);
for (const b of Utils.getEnumValues(Button)) {
if (!this.interactions.hasOwnProperty(b)) return;
this.interactions[b].pressTime = null;
this.interactions[b].isPressed = false;
}
}
isButtonLocked(button: Button): boolean {
return (this.buttonLock === button || this.buttonLock2 === button);
}
setButtonLock(button: Button): void {
if (this.buttonLock === button || this.buttonLock2 === button) return;
if (this.buttonLock === button) this.buttonLock2 = button;
else if (this.buttonLock2 === button) this.buttonLock = button;
else if(!!this.buttonLock) this.buttonLock2 = button;
else this.buttonLock = button;
}
releaseButtonLock(button: Button): void {
if (this.buttonLock === button) this.buttonLock = null;
else if (this.buttonLock2 === button) this.buttonLock2 = null;
}
}

View File

@ -77,6 +77,7 @@ export class LoadingScene extends SceneBase {
this.loadImage('shiny_star_small_1', 'ui', 'shiny_small_1.png');
this.loadImage('shiny_star_small_2', 'ui', 'shiny_small_2.png');
this.loadImage('ha_capsule', 'ui', 'ha_capsule.png');
this.loadImage('champion_ribbon', 'ui', 'champion_ribbon.png');
this.loadImage('icon_spliced', 'ui');
this.loadImage('icon_tera', 'ui');
this.loadImage('type_tera', 'ui');

View File

@ -33,6 +33,7 @@ export const battle: SimpleTranslationEntries = {
"learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.",
"levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!",
"moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.",
"moveNoPP": "There's no PP left for\nthis move!",
"moveDisabled": "{{moveName}} ist deaktiviert!",
"noPokeballForce": "Eine unsichtbare Kraft\nverhindert die Nutzung von Pokébällen.",
"noPokeballTrainer": "Du kannst das Pokémon\neines anderen Trainers nicht fangen!",

28
src/locales/de/config.ts Normal file
View File

@ -0,0 +1,28 @@
import { ability } from "./ability";
import { battle } from "./battle";
import { commandUiHandler } from "./command-ui-handler";
import { fightUiHandler } from "./fight-ui-handler";
import { menu } from "./menu";
import { menuUiHandler } from "./menu-ui-handler";
import { move } from "./move";
import { pokeball } from "./pokeball";
import { pokemon } from "./pokemon";
import { pokemonStat } from "./pokemon-stat";
import { starterSelectUiHandler } from "./starter-select-ui-handler";
import { tutorial } from "./tutorial";
export const deConfig = {
ability: ability,
battle: battle,
commandUiHandler: commandUiHandler,
fightUiHandler: fightUiHandler,
menuUiHandler: menuUiHandler,
menu: menu,
move: move,
pokeball: pokeball,
pokemonStat: pokemonStat,
pokemon: pokemon,
starterSelectUiHandler: starterSelectUiHandler,
tutorial: tutorial
}

View File

@ -43,5 +43,4 @@ export const menu: SimpleTranslationEntries = {
"empty":"Empty",
"yes":"Yes",
"no":"No",
"confirmStartTeam":'Begin with these Pokémon?',
} as const;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
/**
* The menu namespace holds most miscellaneous text that isn't directly part of the game's
* contents or directly related to Pokemon data. This includes menu navigation, settings,
* account interactions, descriptive text, etc.
*/
export const starterSelectUiHandler: SimpleTranslationEntries = {
"confirmStartTeam":'Begin with these Pokémon?',
"growthRate": "Growth Rate:",
"ability": "Ability:",
"passive": "Passive:",
"nature": "Nature:",
"eggMoves": 'Egg Moves',
"start": "Start",
"addToParty": "Add to Party",
"toggleIVs": 'Toggle IVs',
"manageMoves": 'Manage Moves',
"useCandies": 'Use Candies',
"selectMoveSwapOut": "Select a move to swap out.",
"selectMoveSwapWith": "Select a move to swap with",
"unlockPassive": "Unlock Passive",
"reduceCost": "Reduce Cost",
"cycleShiny": "R: Cycle Shiny",
"cycleForm": 'F: Cycle Form',
"cycleGender": 'G: Cycle Gender',
"cycleAbility": 'E: Cycle Ability',
"cycleNature": 'N: Cycle Nature',
"cycleVariant": 'V: Cycle Variant',
"enablePassive": "Enable Passive",
"disablePassive": "Disable Passive"
}

View File

@ -33,6 +33,7 @@ export const battle: SimpleTranslationEntries = {
"learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.",
"levelCapUp": "The level cap\nhas increased to {{levelCap}}!",
"moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.",
"moveNoPP": "There's no PP left for\nthis move!",
"moveDisabled": "{{moveName}} is disabled!",
"noPokeballForce": "An unseen force\nprevents using Poké Balls.",
"noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!",

28
src/locales/en/config.ts Normal file
View File

@ -0,0 +1,28 @@
import { ability } from "./ability";
import { battle } from "./battle";
import { commandUiHandler } from "./command-ui-handler";
import { fightUiHandler } from "./fight-ui-handler";
import { menu } from "./menu";
import { menuUiHandler } from "./menu-ui-handler";
import { move } from "./move";
import { pokeball } from "./pokeball";
import { pokemon } from "./pokemon";
import { pokemonStat } from "./pokemon-stat";
import { starterSelectUiHandler } from "./starter-select-ui-handler";
import { tutorial } from "./tutorial";
export const enConfig = {
ability: ability,
battle: battle,
commandUiHandler: commandUiHandler,
fightUiHandler: fightUiHandler,
menuUiHandler: menuUiHandler,
menu: menu,
move: move,
pokeball: pokeball,
pokemonStat: pokemonStat,
pokemon: pokemon,
starterSelectUiHandler: starterSelectUiHandler,
tutorial: tutorial
}

View File

@ -43,5 +43,4 @@ export const menu: SimpleTranslationEntries = {
"empty":"Empty",
"yes":"Yes",
"no":"No",
"confirmStartTeam":'Begin with these Pokémon?',
} as const;

View File

@ -0,0 +1,32 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
/**
* The menu namespace holds most miscellaneous text that isn't directly part of the game's
* contents or directly related to Pokemon data. This includes menu navigation, settings,
* account interactions, descriptive text, etc.
*/
export const starterSelectUiHandler: SimpleTranslationEntries = {
"confirmStartTeam":'Begin with these Pokémon?',
"growthRate": "Growth Rate:",
"ability": "Ability:",
"passive": "Passive:",
"nature": "Nature:",
"eggMoves": 'Egg Moves',
"start": "Start",
"addToParty": "Add to Party",
"toggleIVs": 'Toggle IVs',
"manageMoves": 'Manage Moves',
"useCandies": 'Use Candies',
"selectMoveSwapOut": "Select a move to swap out.",
"selectMoveSwapWith": "Select a move to swap with",
"unlockPassive": "Unlock Passive",
"reduceCost": "Reduce Cost",
"cycleShiny": "R: Cycle Shiny",
"cycleForm": 'F: Cycle Form',
"cycleGender": 'G: Cycle Gender',
"cycleAbility": 'E: Cycle Ability',
"cycleNature": 'N: Cycle Nature',
"cycleVariant": 'V: Cycle Variant',
"enablePassive": "Enable Passive",
"disablePassive": "Disable Passive"
}

View File

@ -33,6 +33,7 @@ export const battle: SimpleTranslationEntries = {
"learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.",
"levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!",
"moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.",
"moveNoPP": "There's no PP left for\nthis move!",
"moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!",
"noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.",
"noPokeballTrainer": "¡No puedes atrapar a los\nPokémon de los demás!",

28
src/locales/es/config.ts Normal file
View File

@ -0,0 +1,28 @@
import { ability } from "./ability";
import { battle } from "./battle";
import { commandUiHandler } from "./command-ui-handler";
import { fightUiHandler } from "./fight-ui-handler";
import { menu } from "./menu";
import { menuUiHandler } from "./menu-ui-handler";
import { move } from "./move";
import { pokeball } from "./pokeball";
import { pokemon } from "./pokemon";
import { pokemonStat } from "./pokemon-stat";
import { starterSelectUiHandler } from "./starter-select-ui-handler";
import { tutorial } from "./tutorial";
export const esConfig = {
ability: ability,
battle: battle,
commandUiHandler: commandUiHandler,
fightUiHandler: fightUiHandler,
menuUiHandler: menuUiHandler,
menu: menu,
move: move,
pokeball: pokeball,
pokemonStat: pokemonStat,
pokemon: pokemon,
starterSelectUiHandler: starterSelectUiHandler,
tutorial: tutorial
}

View File

@ -13,6 +13,22 @@ export const menu: SimpleTranslationEntries = {
"newGame": "Nueva partida",
"selectGameMode": "Elige un modo de juego.",
"logInOrCreateAccount": "Inicia sesión o crea una cuenta para empezar. ¡No se requiere correo electrónico!",
"username": "Usuario",
"password": "Contraseña",
"login": "Iniciar Sesión",
"register": "Registrarse",
"emptyUsername": "El usuario no puede estar vacío",
"invalidLoginUsername": "El usuario no es válido",
"invalidRegisterUsername": "El usuario solo puede contener letras, números y guiones bajos",
"invalidLoginPassword": "La contraseña no es válida",
"invalidRegisterPassword": "Contraseña debe tener 6 o más caracter.",
"usernameAlreadyUsed": "El usuario ya está en uso",
"accountNonExistent": "El usuario no existe",
"unmatchingPassword": "La contraseña no coincide",
"passwordNotMatchingConfirmPassword": "Las contraseñas deben coincidir",
"confirmPassword": "Confirmar Contra.",
"registrationAgeWarning": "Al registrarte, confirmas tener 13 o más años de edad.",
"backToLogin": "Volver al Login",
"failedToLoadSaveData": "No se ha podido cargar los datos guardados. Por favor, recarga la página.\nSi el fallo continúa, por favor contacta al administrador.",
"sessionSuccess": "Sesión cargada con éxito.",
"failedToLoadSession": "No se ha podido cargar los datos de tu sesión.\nPuede que estén corruptos.",
@ -27,5 +43,4 @@ export const menu: SimpleTranslationEntries = {
"empty":"Vacío",
"yes":"Sí",
"no":"No",
"confirmStartTeam":'¿Comenzar con estos Pokémon?',
} as const;

View File

@ -4,13 +4,13 @@ export const pokemonStat: SimpleTranslationEntries = {
"HP": "PV",
"HPshortened": "PV",
"ATK": "Ataque",
"ATKshortened": "Ataque",
"ATKshortened": "Ata",
"DEF": "Defensa",
"DEFshortened": "Defensa",
"DEFshortened": "Def",
"SPATK": "At. Esp.",
"SPATKshortened": "At. Esp.",
"SPATKshortened": "AtEsp",
"SPDEF": "Def. Esp.",
"SPDEFshortened": "Def. Esp.",
"SPDEFshortened": "DefEsp",
"SPD": "Velocidad",
"SPDshortened": "Veloc."
} as const;

View File

@ -0,0 +1,32 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
/**
* The menu namespace holds most miscellaneous text that isn't directly part of the game's
* contents or directly related to Pokemon data. This includes menu navigation, settings,
* account interactions, descriptive text, etc.
*/
export const starterSelectUiHandler: SimpleTranslationEntries = {
"confirmStartTeam":'¿Comenzar con estos Pokémon?',
"growthRate": "Crecimiento:",
"ability": "Habilid:",
"passive": "Pasiva:",
"nature": "Natur:",
"eggMoves": "Mov. Huevo",
"start": "Iniciar",
"addToParty": "Añadir a Equipo",
"toggleIVs": "Mostrar IVs",
"manageMoves": "Gestionar Movs.",
"useCandies": "Usar Caramelos",
"selectMoveSwapOut": "Elige el movimiento que sustituir.",
"selectMoveSwapWith": "Elige el movimiento que sustituirá a",
"unlockPassive": "Añadir Pasiva",
"reduceCost": "Reducir Coste",
"cycleShiny": "R: Cambiar Shiny",
"cycleForm": 'F: Cambiar Forma',
"cycleGender": 'G: Cambiar Género',
"cycleAbility": 'E: Cambiar Habilidad',
"cycleNature": 'N: Cambiar Naturaleza',
"cycleVariant": 'V: Cambiar Variante',
"enablePassive": "Activar Pasiva",
"disablePassive": "Desactivar Pasiva"
}

View File

@ -10,9 +10,9 @@ export const tutorial: SimpleTranslationEntries = {
$ajustes de tu navegador.`,
"accessMenu": `Para acceder al menú, pulsa M o Escape cuando\ntengas el control.
$El menú contiene la configuración y otras funciones.`,
$El menú contiene los ajustes y otras funciones.`,
"menu": `Desde este menú podrás acceder a la configuración.
"menu": `Desde este menú podrás acceder a los ajustes.
$Podrás cambiar la velocidad del juego, el estilo de la ventana y demás.
$Hay más opciones, ¡así que pruébalas todas!`,

View File

@ -23,7 +23,7 @@ export const battle: SimpleTranslationEntries = {
"attackHitsCount": `Touché {{count}} fois !`,
"expGain": "{{pokemonName}} gagne\n{{exp}} Points dExp !",
"levelUp": "{{pokemonName}} monte au\nN. {{level}} !",
"learnMove": "{{pokemonName}} apprend \n{{moveName}} !",
"learnMove": "{{pokemonName}} apprend\n{{moveName}} !",
"learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.",
"learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.",
"learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?",
@ -33,6 +33,7 @@ export const battle: SimpleTranslationEntries = {
"learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.",
"levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !",
"moveNotImplemented": "{{moveName}} nest pas encore implémenté et ne peut pas être sélectionné.",
"moveNoPP": "Il ny a plus de PP pour\ncette capacité !",
"moveDisabled": "{{moveName}} est sous entrave !",
"noPokeballForce": "Une force mystérieuse\nempêche lutilisation des Poké Balls.",
"noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, cest mal !",

28
src/locales/fr/config.ts Normal file
View File

@ -0,0 +1,28 @@
import { ability } from "./ability";
import { battle } from "./battle";
import { commandUiHandler } from "./command-ui-handler";
import { fightUiHandler } from "./fight-ui-handler";
import { menu } from "./menu";
import { menuUiHandler } from "./menu-ui-handler";
import { move } from "./move";
import { pokeball } from "./pokeball";
import { pokemon } from "./pokemon";
import { pokemonStat } from "./pokemon-stat";
import { starterSelectUiHandler } from "./starter-select-ui-handler";
import { tutorial } from "./tutorial";
export const frConfig = {
ability: ability,
battle: battle,
commandUiHandler: commandUiHandler,
fightUiHandler: fightUiHandler,
menuUiHandler: menuUiHandler,
menu: menu,
move: move,
pokeball: pokeball,
pokemonStat: pokemonStat,
pokemon: pokemon,
starterSelectUiHandler: starterSelectUiHandler,
tutorial: tutorial
}

View File

@ -38,5 +38,4 @@ export const menu: SimpleTranslationEntries = {
"empty":"Vide",
"yes":"Oui",
"no":"Non",
"confirmStartTeam":'Commencer avec ces Pokémon ?',
} as const;

View File

@ -0,0 +1,32 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
/**
* The menu namespace holds most miscellaneous text that isn't directly part of the game's
* contents or directly related to Pokemon data. This includes menu navigation, settings,
* account interactions, descriptive text, etc.
*/
export const starterSelectUiHandler: SimpleTranslationEntries = {
"confirmStartTeam":'Commencer avec ces Pokémon ?',
"growthRate": "Croissance :",
"ability": "Talent :",
"passive": "Passif :",
"nature": "Nature :",
"eggMoves": "Capacités Œuf",
"start": "Lancer",
"addToParty": "Ajouter à léquipe",
"toggleIVs": "Voir IVs",
"manageMoves": "Gérer Capacités",
"useCandies": "Utiliser Bonbons",
"selectMoveSwapOut": "Sélectionnez la capacité à échanger.",
"selectMoveSwapWith": "Sélectionnez laquelle échanger avec",
"unlockPassive": "Débloquer Passif",
"reduceCost": "Diminuer le cout",
"cycleShiny": "R: » Chromatiques",
"cycleForm": "F: » Formes",
"cycleGender": "G: » Sexes",
"cycleAbility": "E: » Talents",
"cycleNature": "N: » Natures",
"cycleVariant": "V: » Variants",
"enablePassive": "Activer Passif",
"disablePassive": "Désactiver Passif"
}

View File

@ -11,18 +11,18 @@ export const battle: SimpleTranslationEntries = {
"trainerGo": "{{trainerName}} manda in campo {{pokemonName}}!",
"switchQuestion": "Vuoi cambiare\n{{pokemonName}}?",
"trainerDefeated": `Hai sconfitto\n{{trainerName}}!`,
"pokemonCaught": "{{pokemonName}} è stato catturato!",
"pokemonCaught": "Preso! {{pokemonName}} è stato catturato!",
"pokemon": "Pokémon",
"sendOutPokemon": "Vai! {{pokemonName}}!",
"hitResultCriticalHit": "Brutto colpo!",
"hitResultSuperEffective": "È superefficace!",
"hitResultNotVeryEffective": "Non è molto efficace…",
"hitResultNoEffect": "Non ha effetto su {{pokemonName}}!",
"hitResultOneHitKO": "È KO con un colpo solo!",
"hitResultOneHitKO": "KO con un colpo!",
"attackFailed": "Ma ha fallito!",
"attackHitsCount": `Colpito {{count}} volta/e!`,
"expGain": "{{pokemonName}} ha guadagnato\n{{exp}} Punti Esperienza!",
"levelUp": "{{pokemonName}} è salito al \nLivello {{level}}!",
"levelUp": "{{pokemonName}} è salito al \nlivello {{level}}!",
"learnMove": "{{pokemonName}} impara \n{{moveName}}!",
"learnMovePrompt": "{{pokemonName}} vorrebbe imparare\n{{moveName}}.",
"learnMoveLimitReached": "Tuttavia, {{pokemonName}} \nconosce già quattro mosse.",
@ -33,15 +33,16 @@ export const battle: SimpleTranslationEntries = {
"learnMoveForgetSuccess": "{{pokemonName}} ha dimenticato la mossa\n{{moveName}}.",
"levelCapUp": "Il livello massimo\nè aumentato a {{levelCap}}!",
"moveNotImplemented": "{{moveName}} non è ancora implementata e non può essere selezionata.",
"moveNoPP": "Non ci sono PP rimanenti\nper questa mossa!",
"moveDisabled": "{{moveName}} è disabilitata!",
"noPokeballForce": "Una forza misteriosa\nimpedisce l'uso dell Poké Ball.",
"noPokeballTrainer": "Non puoi catturare\nPokémon di altri allenatori!",
"noPokeballMulti": "Puoi lanciare una Poké Ball\nquando rimane un solo Pokémon!",
"noPokeballStrong": "Il Pokémon avversario è troppo forte per essere catturato!\nDevi prima indebolirlo!",
"noEscapeForce": "Una forza misteriosa\nimpedisce la fuga.",
"noEscapeTrainer": "Non puoi fuggire\nda una battaglia contro un'allenatore!",
"noEscapeTrainer": "Non puoi sottrarti\nalla lotta con un'allenatore!",
"noEscapePokemon": "{{moveName}} di {{pokemonName}}\npreviene la {{escapeVerb}}!",
"runAwaySuccess": "Sei riuscito a fuggire!",
"runAwaySuccess": "Scampato pericolo!",
"runAwayCannotEscape": 'Non puoi fuggire!',
"escapeVerbSwitch": "cambiando",
"escapeVerbFlee": "fuggendo",

28
src/locales/it/config.ts Normal file
View File

@ -0,0 +1,28 @@
import { ability } from "./ability";
import { battle } from "./battle";
import { commandUiHandler } from "./command-ui-handler";
import { fightUiHandler } from "./fight-ui-handler";
import { menu } from "./menu";
import { menuUiHandler } from "./menu-ui-handler";
import { move } from "./move";
import { pokeball } from "./pokeball";
import { pokemon } from "./pokemon";
import { pokemonStat } from "./pokemon-stat";
import { starterSelectUiHandler } from "./starter-select-ui-handler";
import { tutorial } from "./tutorial";
export const itConfig = {
ability: ability,
battle: battle,
commandUiHandler: commandUiHandler,
fightUiHandler: fightUiHandler,
menuUiHandler: menuUiHandler,
menu: menu,
move: move,
pokeball: pokeball,
pokemonStat: pokemonStat,
pokemon: pokemon,
starterSelectUiHandler: starterSelectUiHandler,
tutorial: tutorial
}

View File

@ -43,5 +43,4 @@ export const menu: SimpleTranslationEntries = {
"empty":"Vuoto",
"yes":"Si",
"no":"No",
"confirmStartTeam":'Vuoi iniziare con questi Pokémon?',
} as const;

View File

@ -0,0 +1,32 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
/**
* The menu namespace holds most miscellaneous text that isn't directly part of the game's
* contents or directly related to Pokemon data. This includes menu navigation, settings,
* account interactions, descriptive text, etc.
*/
export const starterSelectUiHandler: SimpleTranslationEntries = {
"confirmStartTeam":'Vuoi iniziare con questi Pokémon?',
"growthRate": "Vel. Crescita:",
"ability": "Abilità:",
"passive": "Passiva:",
"nature": "Natura:",
"eggMoves": 'Mosse delle uova',
"start": "Inizia",
"addToParty": "Aggiungi al Gruppo",
"toggleIVs": 'Vedi/Nascondi IV',
"manageMoves": 'Gestisci Mosse',
"useCandies": 'Usa Caramelle',
"selectMoveSwapOut": "Seleziona una mossa da scambiare.",
"selectMoveSwapWith": "Seleziona una mossa da scambiare con",
"unlockPassive": "Sblocca Passiva",
"reduceCost": "Riduci Costo",
"cycleShiny": "R: Alterna Shiny",
"cycleForm": 'F: Alterna Forma',
"cycleGender": 'G: Alterna Sesso',
"cycleAbility": 'E: Alterna Abilità',
"cycleNature": 'N: Alterna Natura',
"cycleVariant": 'V: Alterna Variante',
"enablePassive": "Attiva Passiva",
"disablePassive": "Disattiva Passiva"
}

View File

@ -144,9 +144,16 @@ class AddPokeballModifierType extends ModifierType implements Localizable {
}
localize(): void {
// TODO: Actually use i18n to localize this description.
this.name = `${this.count}x ${getPokeballName(this.pokeballType)}`;
this.description = `Receive ${getPokeballName(this.pokeballType)} x${this.count}\nCatch Rate: ${getPokeballCatchMultiplier(this.pokeballType) > -1 ? `${getPokeballCatchMultiplier(this.pokeballType)}x` : 'Certain'}`;
this.description = `Receive ${getPokeballName(this.pokeballType)} x${this.count} (Inventory: {AMOUNT}) \nCatch Rate: ${getPokeballCatchMultiplier(this.pokeballType) > -1 ? `${getPokeballCatchMultiplier(this.pokeballType)}x` : 'Certain'}`;
}
getDescription(scene: BattleScene): string {
this.localize();
return this.description.replace('{AMOUNT}', scene.pokeballCounts[this.pokeballType].toString());
}
}
class AddVoucherModifierType extends ModifierType {
@ -299,7 +306,7 @@ export class PokemonNatureChangeModifierType extends PokemonModifierType {
protected nature: Nature;
constructor(nature: Nature) {
super(`${getNatureName(nature)} Mint`, `Changes a Pokémon\'s nature to ${getNatureName(nature, true, true, true)}`, ((_type, args) => new Modifiers.PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)),
super(`${getNatureName(nature)} Mint`, `Changes a Pokémon\'s nature to ${getNatureName(nature, true, true, true)} and permanently unlocks the nature for the starter.`, ((_type, args) => new Modifiers.PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)),
((pokemon: PlayerPokemon) => {
if (pokemon.getNature() === this.nature)
return PartyUiHandler.NoEffectMessage;
@ -997,7 +1004,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
return faintedPartyMemberCount * 9;
}, 3),
}, 27),
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
return faintedPartyMemberCount * 3;

View File

@ -8,15 +8,14 @@ import { Stat } from "../data/pokemon-stat";
import { addTextObject, TextStyle } from "../ui/text";
import { Type } from '../data/type';
import { EvolutionPhase } from '../evolution-phase';
import { FusionSpeciesFormEvolution, pokemonEvolutions } from '../data/pokemon-evolutions';
import { FusionSpeciesFormEvolution, pokemonEvolutions, pokemonPrevolutions } from '../data/pokemon-evolutions';
import { getPokemonMessage } from '../messages';
import * as Utils from "../utils";
import { TempBattleStat } from '../data/temp-battle-stat';
import { BerryType, getBerryEffectFunc, getBerryPredicate } from '../data/berry';
import { StatusEffect, getStatusEffectHealText } from '../data/status-effect';
import { MoneyAchv, achvs } from '../system/achv';
import { achvs } from '../system/achv';
import { VoucherType } from '../system/voucher';
import { PreventBerryUseAbAttr, applyAbAttrs } from '../data/ability';
import { FormChangeItem, SpeciesFormChangeItemTrigger } from '../data/pokemon-forms';
import { Nature } from '#app/data/nature';
import { BattlerTagType } from '#app/data/enums/battler-tag-type';
@ -1090,6 +1089,13 @@ export class PokemonNatureChangeModifier extends ConsumablePokemonModifier {
apply(args: any[]): boolean {
const pokemon = args[0] as Pokemon;
pokemon.natureOverride = this.nature;
let speciesId = pokemon.species.speciesId;
pokemon.scene.gameData.dexData[speciesId].natureAttr |= Math.pow(2, this.nature + 1);
while (pokemonPrevolutions.hasOwnProperty(speciesId)) {
speciesId = pokemonPrevolutions[speciesId];
pokemon.scene.gameData.dexData[speciesId].natureAttr |= Math.pow(2, this.nature + 1);
}
return true;
}

View File

@ -12,12 +12,15 @@ export const STARTING_WAVE_OVERRIDE = 0;
export const STARTING_BIOME_OVERRIDE = Biome.TOWN;
export const STARTING_MONEY_OVERRIDE = 0;
export const WEATHER_OVERRIDE = WeatherType.NONE;
export const DOUBLE_BATTLE_OVERRIDE = false;
export const ABILITY_OVERRIDE = Abilities.NONE;
export const PASSIVE_ABILITY_OVERRIDE = Abilities.NONE;
export const MOVE_OVERRIDE = Moves.NONE;
export const MOVE_OVERRIDE_2 = Moves.NONE;
export const OPP_SPECIES_OVERRIDE = 0;
export const OPP_ABILITY_OVERRIDE = Abilities.NONE;
export const OPP_PASSIVE_ABILITY_OVERRIDE = Abilities.NONE;
export const OPP_MOVE_OVERRIDE = Moves.NONE;
export const OPP_MOVE_OVERRIDE_2 = Moves.NONE;

View File

@ -1,8 +1,8 @@
import BattleScene, { bypassLogin, startingWave } from "./battle-scene";
import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene";
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon";
import * as Utils from './utils';
import { Moves } from "./data/enums/moves";
import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move";
import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move";
import { Mode } from './ui/ui';
import { Command } from "./ui/command-ui-handler";
import { Stat } from "./data/pokemon-stat";
@ -55,7 +55,7 @@ import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select
import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler";
import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run";
import { GameModes, gameModes } from "./game-mode";
import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species";
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./data/pokemon-species";
import i18next from './plugins/i18n';
import { Abilities } from "./data/enums/abilities";
import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides';
@ -1680,21 +1680,13 @@ export class CommandPhase extends FieldPhase {
switch (command) {
case Command.FIGHT:
let useStruggle = false;
if (cursor === -1 || playerPokemon.trySelectMove(cursor, args[0] as boolean) || (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) {
if (cursor === -1 ||
playerPokemon.trySelectMove(cursor, args[0] as boolean) ||
(useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) {
const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor].moveId : Moves.NONE : Moves.STRUGGLE;
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args };
const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, moveId) : args[2];
if (moveId) {
const move = playerPokemon.getMoveset()[cursor];
if (move.getName().endsWith(' (N)')) {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('battle:moveNotImplemented', { moveName: move.getName().slice(0, -4) }), null, () => {
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
}, null, true);
return;
}
} else
if (!moveId)
turnCommand.targets = [ this.fieldIndex ];
console.log(moveTargets, playerPokemon.name);
if (moveTargets.targets.length <= 1 || moveTargets.multiple)
@ -1705,15 +1697,21 @@ export class CommandPhase extends FieldPhase {
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
success = true;
} else if (cursor < playerPokemon.getMoveset().length) {
}
else if (cursor < playerPokemon.getMoveset().length) {
const move = playerPokemon.getMoveset()[cursor];
if (playerPokemon.summonData.disabledMove === move.moveId) {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('battle:moveDisabled', { moveName: move.getName() }), null, () => {
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
}, null, true);
}
this.scene.ui.setMode(Mode.MESSAGE);
// Decides between a Disabled, Not Implemented, or No PP translation message
const errorMessage =
playerPokemon.summonData.disabledMove === move.moveId ? 'battle:moveDisabled' :
move.getName().endsWith(' (N)') ? 'battle:moveNotImplemented' : 'battle:moveNoPP';
const moveName = move.getName().replace(' (N)', ''); // Trims off the indicator
this.scene.ui.showText(i18next.t(errorMessage, { moveName: moveName }), null, () => {
this.scene.ui.clearText();
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
}, null, true);
}
break;
case Command.BALL:
@ -3144,8 +3142,16 @@ export class FaintPhase extends PokemonPhase {
alivePlayField.forEach(p => applyPostKnockOutAbAttrs(PostKnockOutAbAttr, p, pokemon));
if (pokemon.turnData?.attacksReceived?.length) {
const defeatSource = this.scene.getPokemonById(pokemon.turnData.attacksReceived[0].sourceId);
if (defeatSource?.isOnField())
if (defeatSource?.isOnField()) {
applyPostVictoryAbAttrs(PostVictoryAbAttr, defeatSource);
const pvmove = allMoves[pokemon.turnData.attacksReceived[0].move];
const pvattrs = pvmove.getAttrs(PostVictoryStatChangeAttr);
if (pvattrs.length) {
for (let pvattr of pvattrs) {
pvattr.applyPostVictory(defeatSource, defeatSource, pvmove);
}
}
}
}
if (this.player) {
@ -3474,8 +3480,40 @@ export class GameOverModifierRewardPhase extends ModifierRewardPhase {
}
}
export class RibbonModifierRewardPhase extends ModifierRewardPhase {
private species: PokemonSpecies;
constructor(scene: BattleScene, modifierTypeFunc: ModifierTypeFunc, species: PokemonSpecies) {
super(scene, modifierTypeFunc);
this.species = species;
}
doReward(): Promise<void> {
return new Promise<void>(resolve => {
const newModifier = this.modifierType.newModifier();
this.scene.addModifier(newModifier).then(() => {
this.scene.gameData.saveSystem().then(success => {
if (success) {
this.scene.playSound('level_up_fanfare');
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.arenaBg.setVisible(false);
this.scene.ui.fadeIn(250).then(() => {
this.scene.ui.showText(`${this.species.name} beat ${this.scene.gameMode.getName()} Mode for the first time!\nYou received ${newModifier.type.name}!`, null, () => {
resolve();
}, null, true, 1500);
});
} else
this.scene.reset(true);
});
});
})
}
}
export class GameOverPhase extends BattlePhase {
private victory: boolean;
private firstRibbons: PokemonSpecies[] = [];
constructor(scene: BattleScene, victory?: boolean) {
super(scene);
@ -3527,6 +3565,13 @@ export class GameOverPhase extends BattlePhase {
if (this.scene.gameMode.isClassic) {
firstClear = this.scene.validateAchv(achvs.CLASSIC_VICTORY);
this.scene.gameData.gameStats.sessionsWon++;
for (let pokemon of this.scene.getParty()) {
this.awardRibbon(pokemon);
if (pokemon.species.getRootSpeciesId() != pokemon.species.getRootSpeciesId(true)) {
this.awardRibbon(pokemon, true);
}
}
} else if (this.scene.gameMode.isDaily && success[1])
this.scene.gameData.gameStats.dailyRunSessionsWon++;
}
@ -3538,8 +3583,12 @@ export class GameOverPhase extends BattlePhase {
this.scene.clearPhaseQueue();
this.scene.ui.clearText();
this.handleUnlocks();
if (this.victory && !firstClear && success[1])
this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM));
if (this.victory && success[1]) {
for (let species of this.firstRibbons)
this.scene.unshiftPhase(new RibbonModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PLUS, species));
if (!firstClear)
this.scene.unshiftPhase(new GameOverModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PREMIUM));
}
this.scene.reset();
this.scene.unshiftPhase(new TitlePhase(this.scene));
this.end();
@ -3558,6 +3607,15 @@ export class GameOverPhase extends BattlePhase {
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.MINI_BLACK_HOLE));
}
}
awardRibbon(pokemon: Pokemon, forStarter: boolean = false): void {
const speciesId = getPokemonSpecies(pokemon.species.speciesId)
const speciesRibbonCount = this.scene.gameData.incrementRibbonCount(speciesId, forStarter);
// first time classic win, award voucher
if (speciesRibbonCount === 1) {
this.firstRibbons.push(getPokemonSpecies(pokemon.species.getRootSpeciesId(forStarter)));
}
}
}
export class UnlockPhase extends Phase {

View File

@ -1,71 +1,11 @@
import i18next from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { menu as enMenu } from '../locales/en/menu';
import { menu as esMenu } from '../locales/es/menu';
import { menu as itMenu } from '../locales/it/menu';
import { menu as frMenu } from '../locales/fr/menu';
import { menu as deMenu } from '../locales/de/menu';
import { menuUiHandler as enMenuUiHandler } from '../locales/en/menu-ui-handler.js';
import { menuUiHandler as esMenuUiHandler } from '../locales/es/menu-ui-handler.js';
import { menuUiHandler as frMenuUiHandler } from '../locales/fr/menu-ui-handler.js';
import { menuUiHandler as itMenuUiHandler } from '../locales/it/menu-ui-handler.js';
import { menuUiHandler as deMenuUiHandler } from '../locales/de/menu-ui-handler.js';
import { battle as enBattle } from '../locales/en/battle';
import { battle as esBattle } from '../locales/es/battle';
import { battle as itBattle } from '../locales/it/battle';
import { battle as frBattle } from '../locales/fr/battle';
import { battle as deBattle } from '../locales/de/battle';
import { move as enMove } from '../locales/en/move';
import { move as esMove } from '../locales/es/move';
import { move as itMove } from '../locales/it/move';
import { move as frMove } from '../locales/fr/move';
import { move as deMove } from '../locales/de/move';
import { ability as enAbility } from '../locales/en/ability';
import { ability as esAbility } from '../locales/es/ability';
import { ability as itAbility } from '../locales/it/ability';
import { ability as frAbility } from '../locales/fr/ability';
import { ability as deAbility } from '../locales/de/ability';
import { pokeball as enPokeball } from '../locales/en/pokeball';
import { pokeball as esPokeball } from '../locales/es/pokeball';
import { pokeball as itPokeball } from '../locales/it/pokeball';
import { pokeball as frPokeball } from '../locales/fr/pokeball';
import { pokeball as dePokeball } from '../locales/de/pokeball';
import { pokemon as enPokemon } from '../locales/en/pokemon';
import { pokemon as esPokemon } from '../locales/es/pokemon';
import { pokemon as itPokemon } from '../locales/it/pokemon';
import { pokemon as frPokemon } from '../locales/fr/pokemon';
import { pokemon as dePokemon } from '../locales/de/pokemon';
import { pokemonStat as enPokemonStat } from '../locales/en/pokemon-stat';
import { pokemonStat as esPokemonStat } from '../locales/es/pokemon-stat';
import { pokemonStat as frPokemonStat } from '../locales/fr/pokemon-stat';
import { pokemonStat as itPokemonStat } from '../locales/it/pokemon-stat';
import { pokemonStat as dePokemonStat } from '../locales/de/pokemon-stat';
import { commandUiHandler as enCommandUiHandler } from '../locales/en/command-ui-handler';
import { commandUiHandler as esCommandUiHandler } from '../locales/es/command-ui-handler';
import { commandUiHandler as itCommandUiHandler } from '../locales/it/command-ui-handler';
import { commandUiHandler as frCommandUiHandler } from '../locales/fr/command-ui-handler';
import { commandUiHandler as deCommandUiHandler } from '../locales/de/command-ui-handler';
import { fightUiHandler as enFightUiHandler } from '../locales/en/fight-ui-handler';
import { fightUiHandler as esFightUiHandler } from '../locales/es/fight-ui-handler';
import { fightUiHandler as frFightUiHandler } from '../locales/fr/fight-ui-handler';
import { fightUiHandler as itFightUiHandler } from '../locales/it/fight-ui-handler';
import { fightUiHandler as deFightUiHandler } from '../locales/de/fight-ui-handler';
import { tutorial as enTutorial } from '../locales/en/tutorial';
import { tutorial as esTutorial } from '../locales/es/tutorial';
import { tutorial as frTutorial } from '../locales/fr/tutorial';
import { tutorial as itTutorial} from '../locales/it/tutorial';
import { tutorial as deTutorial } from '../locales/de/tutorial';
import { deConfig } from '#app/locales/de/config.js';
import { enConfig } from '#app/locales/en/config.js';
import { esConfig } from '#app/locales/es/config.js';
import { frConfig } from '#app/locales/fr/config.js';
import { itConfig } from '#app/locales/it/config.js';
export interface SimpleTranslationEntries {
[key: string]: string
@ -125,69 +65,19 @@ export function initI18n(): void {
},
resources: {
en: {
menu: enMenu,
menuUiHandler: enMenuUiHandler,
battle: enBattle,
move: enMove,
ability: enAbility,
pokeball: enPokeball,
pokemon: enPokemon,
pokemonStat: enPokemonStat,
commandUiHandler: enCommandUiHandler,
fightUiHandler: enFightUiHandler,
tutorial: enTutorial,
...enConfig
},
es: {
menu: esMenu,
menuUiHandler: esMenuUiHandler,
battle: esBattle,
move: esMove,
ability: esAbility,
pokeball: esPokeball,
pokemon: esPokemon,
pokemonStat: esPokemonStat,
commandUiHandler: esCommandUiHandler,
fightUiHandler: esFightUiHandler,
tutorial: esTutorial,
...esConfig
},
fr: {
menu: frMenu,
menuUiHandler: frMenuUiHandler,
battle: frBattle,
move: frMove,
ability: frAbility,
pokeball: frPokeball,
pokemon: frPokemon,
pokemonStat: frPokemonStat,
commandUiHandler: frCommandUiHandler,
fightUiHandler: frFightUiHandler,
tutorial: frTutorial,
...frConfig
},
it: {
menu: itMenu,
menuUiHandler: itMenuUiHandler,
battle: itBattle,
move: itMove,
ability: itAbility,
pokeball: itPokeball,
pokemon: itPokemon,
pokemonStat: itPokemonStat,
commandUiHandler: itCommandUiHandler,
fightUiHandler: itFightUiHandler,
tutorial: itTutorial,
...itConfig
},
de: {
menu: deMenu,
menuUiHandler: deMenuUiHandler,
battle: deBattle,
move: deMove,
ability: deAbility,
pokeball: dePokeball,
pokemon: dePokemon,
pokemonStat: dePokemonStat,
commandUiHandler: deCommandUiHandler,
fightUiHandler: deFightUiHandler,
tutorial: deTutorial,
...deConfig
}
},
});
@ -197,17 +87,18 @@ export function initI18n(): void {
declare module 'i18next' {
interface CustomTypeOptions {
resources: {
menu: typeof enMenu;
menuUiHandler: typeof enMenuUiHandler;
move: typeof enMove;
battle: typeof enBattle,
ability: typeof enAbility;
pokeball: typeof enPokeball;
pokemon: typeof enPokemon;
pokemonStat: typeof enPokemonStat;
commandUiHandler: typeof enCommandUiHandler;
fightUiHandler: typeof enFightUiHandler;
tutorial: typeof enTutorial;
menu: SimpleTranslationEntries;
menuUiHandler: SimpleTranslationEntries;
move: MoveTranslationEntries;
battle: SimpleTranslationEntries,
ability: AbilityTranslationEntries;
pokeball: SimpleTranslationEntries;
pokemon: SimpleTranslationEntries;
pokemonStat: SimpleTranslationEntries;
commandUiHandler: SimpleTranslationEntries;
fightUiHandler: SimpleTranslationEntries;
tutorial: SimpleTranslationEntries;
starterSelectUiHandler: SimpleTranslationEntries;
};
}
}

View File

@ -51,9 +51,9 @@ export class Achv {
}
getTier(): AchvTier {
if (this.score >= 150)
return AchvTier.MASTER;
if (this.score >= 100)
return AchvTier.MASTER;
if (this.score >= 75)
return AchvTier.ROGUE;
if (this.score >= 50)
return AchvTier.ULTRA;
@ -73,6 +73,16 @@ export class MoneyAchv extends Achv {
}
}
export class RibbonAchv extends Achv {
private ribbonAmount: integer;
constructor(name: string, ribbonAmount: integer, iconImage: string, score: integer) {
super(name, `Accumulate a total of ${ribbonAmount.toLocaleString('en-US')} Ribbons`, iconImage, score, (scene: BattleScene, _args: any[]) => scene.gameData.gameStats.ribbonsOwned >= this.ribbonAmount);
this.ribbonAmount = ribbonAmount;
}
}
export class DamageAchv extends Achv {
private damageAmount: integer;
@ -125,6 +135,11 @@ export const achvs = {
LV_100: new LevelAchv('But Wait, There\'s More!', 100, 'rare_candy', 25).setSecret(),
LV_250: new LevelAchv('Elite', 250, 'rarer_candy', 50).setSecret(true),
LV_1000: new LevelAchv('To Go Even Further Beyond', 1000, 'candy_jar', 100).setSecret(true),
_10_RIBBONS: new RibbonAchv('Pokémon League Champion', 10, 'bronze_ribbon', 10),
_25_RIBBONS: new RibbonAchv('Great League Champion', 25, 'great_ribbon', 25).setSecret(true),
_50_RIBBONS: new RibbonAchv('Ultra League Champion', 50, 'ultra_ribbon', 50).setSecret(true),
_75_RIBBONS: new RibbonAchv('Rogue League Champion', 75, 'rogue_ribbon', 75).setSecret(true),
_100_RIBBONS: new RibbonAchv('Master League Champion', 100, 'master_ribbon', 100).setSecret(true),
TRANSFER_MAX_BATTLE_STAT: new Achv('Teamwork', 'Baton pass to another party member with at least one stat maxed out', 'stick', 20),
MAX_FRIENDSHIP: new Achv('Friendmaxxing', 'Reach max friendship on a Pokémon', 'soothe_bell', 25),
MEGA_EVOLVE: new Achv('Megamorph', 'Mega evolve a Pokémon', 'mega_bracelet', 50),

View File

@ -173,6 +173,7 @@ export interface StarterDataEntry {
abilityAttr: integer;
passiveAttr: integer;
valueReduction: integer;
classicWinCount: integer;
}
export interface StarterData {
@ -194,7 +195,8 @@ const systemShortKeys = {
eggMoves: '$em',
candyCount: '$x',
passive: '$p',
valueReduction: '$vr'
valueReduction: '$vr',
classicWinCount: '$wc'
};
export class GameData {
@ -248,58 +250,52 @@ export class GameData {
public saveSystem(): Promise<boolean> {
return new Promise<boolean>(resolve => {
this.scene.ui.savingIcon.show();
updateUserInfo().then(response => {
if (!response[0]) {
this.scene.ui.savingIcon.hide();
return resolve(false);
}
const data: SystemSaveData = {
trainerId: this.trainerId,
secretId: this.secretId,
gender: this.gender,
dexData: this.dexData,
starterData: this.starterData,
gameStats: this.gameStats,
unlocks: this.unlocks,
achvUnlocks: this.achvUnlocks,
voucherUnlocks: this.voucherUnlocks,
voucherCounts: this.voucherCounts,
eggs: this.eggs.map(e => new EggData(e)),
gameVersion: this.scene.game.config.gameVersion,
timestamp: new Date().getTime()
};
const data: SystemSaveData = {
trainerId: this.trainerId,
secretId: this.secretId,
gender: this.gender,
dexData: this.dexData,
starterData: this.starterData,
gameStats: this.gameStats,
unlocks: this.unlocks,
achvUnlocks: this.achvUnlocks,
voucherUnlocks: this.voucherUnlocks,
voucherCounts: this.voucherCounts,
eggs: this.eggs.map(e => new EggData(e)),
gameVersion: this.scene.game.config.gameVersion,
timestamp: new Date().getTime()
};
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);
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) {
Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true)
.then(response => response.text())
.then(error => {
this.scene.ui.savingIcon.hide();
if (error) {
if (error.startsWith('client version out of date')) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
} else if (error.startsWith('session out of date')) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
}
console.error(error);
return resolve(false);
if (!bypassLogin) {
Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true)
.then(response => response.text())
.then(error => {
this.scene.ui.savingIcon.hide();
if (error) {
if (error.startsWith('client version out of date')) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
} else if (error.startsWith('session out of date')) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
}
resolve(true);
});
} else {
localStorage.setItem('data_bak', localStorage.getItem('data'));
console.error(error);
return resolve(false);
}
resolve(true);
});
} else {
localStorage.setItem('data_bak', localStorage.getItem('data'));
localStorage.setItem('data', btoa(systemData));
localStorage.setItem('data', btoa(systemData));
this.scene.ui.savingIcon.hide();
this.scene.ui.savingIcon.hide();
resolve(true);
}
});
resolve(true);
}
});
}
@ -995,7 +991,8 @@ export class GameData {
friendship: 0,
abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0,
passiveAttr: 0,
valueReduction: 0
valueReduction: 0,
classicWinCount: 0
};
}
@ -1089,6 +1086,32 @@ export class GameData {
});
}
incrementRibbonCount(species: PokemonSpecies, forStarter: boolean = false): integer {
const speciesIdToIncrement: Species = species.getRootSpeciesId(forStarter);
if (!this.starterData[speciesIdToIncrement].classicWinCount) {
this.starterData[speciesIdToIncrement].classicWinCount = 0;
}
if (!this.starterData[speciesIdToIncrement].classicWinCount)
this.scene.gameData.gameStats.ribbonsOwned++;
const ribbonsInStats: integer = this.scene.gameData.gameStats.ribbonsOwned;
if (ribbonsInStats >= 100)
this.scene.validateAchv(achvs._100_RIBBONS);
if (ribbonsInStats >= 75)
this.scene.validateAchv(achvs._75_RIBBONS);
if (ribbonsInStats >= 50)
this.scene.validateAchv(achvs._50_RIBBONS);
if (ribbonsInStats >= 25)
this.scene.validateAchv(achvs._25_RIBBONS);
if (ribbonsInStats >= 10)
this.scene.validateAchv(achvs._10_RIBBONS);
return ++this.starterData[speciesIdToIncrement].classicWinCount;
}
addStarterCandy(species: PokemonSpecies, count: integer): void {
this.scene.candyBar.showStarterSpeciesCandy(species.speciesId, count);
this.starterData[species.speciesId].candyCount += count;

View File

@ -6,6 +6,7 @@ export class GameStats {
public battles: integer;
public classicSessionsPlayed: integer;
public sessionsWon: integer;
public ribbonsOwned: integer;
public dailyRunSessionsPlayed: integer;
public dailyRunSessionsWon: integer;
public endlessSessionsPlayed: integer;
@ -43,6 +44,7 @@ export class GameStats {
this.battles = source?.battles || 0;
this.classicSessionsPlayed = source?.classicSessionsPlayed || 0;
this.sessionsWon = source?.sessionsWon || 0;
this.ribbonsOwned = source?.ribbonsOwned || 0;
this.dailyRunSessionsPlayed = source?.dailyRunSessionsPlayed || 0;
this.dailyRunSessionsWon = source?.dailyRunSessionsWon || 0;
this.endlessSessionsPlayed = source?.endlessSessionsPlayed || 0;
@ -64,7 +66,7 @@ export class GameStats {
this.legendaryPokemonHatched = source?.legendaryPokemonHatched || 0;
this.mythicalPokemonSeen = source?.mythicalPokemonSeen || 0;
this.mythicalPokemonCaught = source?.mythicalPokemonCaught || 0;
this.mythicalPokemonHatched = source?.mythicalPokemonCaught || 0;
this.mythicalPokemonHatched = source?.mythicalPokemonHatched || 0;
this.shinyPokemonSeen = source?.shinyPokemonSeen || 0;
this.shinyPokemonCaught = source?.shinyPokemonCaught || 0;
this.shinyPokemonHatched = source?.shinyPokemonHatched || 0;

View File

@ -51,6 +51,7 @@ const displayStats: DisplayStats = {
return `${caughtCount} (${Math.floor((caughtCount / Object.keys(gameData.dexData).length) * 1000) / 10}%)`;
}
},
ribbonsOwned: 'Ribbons Owned',
classicSessionsPlayed: 'Classic Runs',
sessionsWon: 'Classic Wins',
dailyRunSessionsPlayed: 'Daily Run Attempts',

View File

@ -174,6 +174,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private starterValueLabels: Phaser.GameObjects.Text[];
private shinyIcons: Phaser.GameObjects.Image[][];
private hiddenAbilityIcons: Phaser.GameObjects.Image[];
private classicWinIcons: Phaser.GameObjects.Image[];
private iconAnimHandler: PokemonIconAnimHandler;
@ -227,7 +228,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonNameText.setOrigin(0, 0);
this.starterSelectContainer.add(this.pokemonNameText);
this.pokemonGrowthRateLabelText = addTextObject(this.scene, 8, 106, 'Growth Rate:', TextStyle.SUMMARY_ALT, { fontSize: '36px' });
this.pokemonGrowthRateLabelText = addTextObject(this.scene, 8, 106, i18next.t("starterSelectUiHandler:growthRate"), TextStyle.SUMMARY_ALT, { fontSize: '36px' });
this.pokemonGrowthRateLabelText.setOrigin(0, 0);
this.pokemonGrowthRateLabelText.setVisible(false);
this.starterSelectContainer.add(this.pokemonGrowthRateLabelText);
@ -244,7 +245,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonUncaughtText.setOrigin(0, 0);
this.starterSelectContainer.add(this.pokemonUncaughtText);
this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 127, 'Ability:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 127, i18next.t("starterSelectUiHandler:ability"), TextStyle.SUMMARY_ALT, { fontSize: '56px' });
this.pokemonAbilityLabelText.setOrigin(0, 0);
this.pokemonAbilityLabelText.setVisible(false);
this.starterSelectContainer.add(this.pokemonAbilityLabelText);
@ -253,7 +254,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonAbilityText.setOrigin(0, 0);
this.starterSelectContainer.add(this.pokemonAbilityText);
this.pokemonPassiveLabelText = addTextObject(this.scene, 6, 136, 'Passive:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
this.pokemonPassiveLabelText = addTextObject(this.scene, 6, 136, i18next.t("starterSelectUiHandler:passive"), TextStyle.SUMMARY_ALT, { fontSize: '56px' });
this.pokemonPassiveLabelText.setOrigin(0, 0);
this.pokemonPassiveLabelText.setVisible(false);
this.starterSelectContainer.add(this.pokemonPassiveLabelText);
@ -262,7 +263,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonPassiveText.setOrigin(0, 0);
this.starterSelectContainer.add(this.pokemonPassiveText);
this.pokemonNatureLabelText = addTextObject(this.scene, 6, 145, 'Nature:', TextStyle.SUMMARY_ALT, { fontSize: '56px' });
this.pokemonNatureLabelText = addTextObject(this.scene, 6, 145, i18next.t("starterSelectUiHandler:nature"), TextStyle.SUMMARY_ALT, { fontSize: '56px' });
this.pokemonNatureLabelText.setOrigin(0, 0);
this.pokemonNatureLabelText.setVisible(false);
this.starterSelectContainer.add(this.pokemonNatureLabelText);
@ -327,7 +328,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.valueLimitLabel.setOrigin(0.5, 0);
this.starterSelectContainer.add(this.valueLimitLabel);
const startLabel = addTextObject(this.scene, 124, 162, 'Start', TextStyle.TOOLTIP_CONTENT);
const startLabel = addTextObject(this.scene, 124, 162, i18next.t("starterSelectUiHandler:start"), TextStyle.TOOLTIP_CONTENT);
startLabel.setOrigin(0.5, 0);
this.starterSelectContainer.add(startLabel);
@ -410,6 +411,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
return ret;
});
this.classicWinIcons = new Array(81).fill(null).map((_, i) => {
const x = (i % 9) * 18;
const y = Math.floor(i / 9) * 18;
const ret = this.scene.add.image(x + 152, y + 16, 'champion_ribbon');
ret.setOrigin(0, 0);
ret.setScale(0.5);
ret.setVisible(false);
this.starterSelectContainer.add(ret);
return ret;
});
this.pokemonSprite = this.scene.add.sprite(53, 63, `pkmn__sub`);
this.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
this.starterSelectContainer.add(this.pokemonSprite);
@ -512,7 +524,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonEggMovesContainer = this.scene.add.container(102, 85);
this.pokemonEggMovesContainer.setScale(0.375);
const eggMovesLabel = addTextObject(this.scene, -46, 0, 'Egg Moves', TextStyle.WINDOW_ALT);
const eggMovesLabel = addTextObject(this.scene, -46, 0, i18next.t("starterSelectUiHandler:eggMoves"), TextStyle.WINDOW_ALT);
eggMovesLabel.setOrigin(0.5, 0);
this.pokemonEggMovesContainer.add(eggMovesLabel);
@ -734,7 +746,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
else if (this.starterCursors.length < 6) {
const options = [
{
label: 'Add to Party',
label: i18next.t("starterSelectUiHandler:addToParty"),
handler: () => {
ui.setMode(Mode.STARTER_SELECT);
let isDupe = false;
@ -771,7 +783,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
overrideSound: true
},
{
label: 'Toggle IVs',
label: i18next.t("starterSelectUiHandler:toggleIVs"),
handler: () => {
this.toggleStatsMode();
ui.setMode(Mode.STARTER_SELECT);
@ -782,14 +794,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (this.speciesStarterMoves.length > 1) {
const showSwapOptions = (moveset: StarterMoveset) => {
ui.setMode(Mode.STARTER_SELECT).then(() => {
ui.showText('Select a move to swap out.', null, () => {
ui.showText(i18next.t("starterSelectUiHandler:selectMoveSwapOut"), null, () => {
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
options: moveset.map((m: Moves, i: number) => {
const option: OptionSelectItem = {
label: allMoves[m].name,
handler: () => {
ui.setMode(Mode.STARTER_SELECT).then(() => {
ui.showText(`Select a move to swap with ${allMoves[m].name}.`, null, () => {
ui.showText(`${i18next.t("starterSelectUiHandler:selectMoveSwapWith")} ${allMoves[m].name}.`, null, () => {
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
options: this.speciesStarterMoves.filter((sm: Moves) => sm !== m).map(sm => {
// make an option for each available starter move
@ -803,7 +815,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
};
return option;
}).concat({
label: 'Cancel',
label: i18next.t("menu:cancel"),
handler: () => {
showSwapOptions(this.starterMoveset);
return true;
@ -819,7 +831,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
};
return option;
}).concat({
label: 'Cancel',
label: i18next.t("menu:cancel"),
handler: () => {
this.clearText();
ui.setMode(Mode.STARTER_SELECT);
@ -833,7 +845,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
});
};
options.push({
label: 'Manage Moves',
label: i18next.t("starterSelectUiHandler:manageMoves"),
handler: () => {
showSwapOptions(this.starterMoveset);
return true;
@ -846,7 +858,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (passiveAttr & PassiveAttr.UNLOCKED) {
if (!(passiveAttr & PassiveAttr.ENABLED)) {
options.push({
label: 'Enable Passive',
label: i18next.t("starterSelectUiHandler:enablePassive"),
handler: () => {
starterData.passiveAttr |= PassiveAttr.ENABLED;
ui.setMode(Mode.STARTER_SELECT);
@ -856,7 +868,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
});
} else {
options.push({
label: 'Disable Passive',
label: i18next.t("starterSelectUiHandler:disablePassive"),
handler: () => {
starterData.passiveAttr ^= PassiveAttr.ENABLED;
ui.setMode(Mode.STARTER_SELECT);
@ -871,7 +883,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (!(passiveAttr & PassiveAttr.UNLOCKED)) {
const passiveCost = getPassiveCandyCount(speciesStarters[this.lastSpecies.speciesId]);
options.push({
label: `x${passiveCost} Unlock Passive (${allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name})`,
label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name})`,
handler: () => {
if (candyCount >= passiveCost) {
starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED;
@ -895,7 +907,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (valueReduction < 2) {
const reductionCost = getValueReductionCandyCounts(speciesStarters[this.lastSpecies.speciesId])[valueReduction];
options.push({
label: `x${reductionCost} Reduce Cost`,
label: `x${reductionCost} ${i18next.t("starterSelectUiHandler:reduceCost")}`,
handler: () => {
if (candyCount >= reductionCost) {
starterData.valueReduction++;
@ -918,7 +930,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
});
}
options.push({
label: 'Cancel',
label: i18next.t("menu:cancel"),
handler: () => {
ui.setMode(Mode.STARTER_SELECT);
return true;
@ -931,7 +943,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
};
if (!pokemonPrevolutions.hasOwnProperty(this.lastSpecies.speciesId)) {
options.push({
label: 'Use Candies',
label: i18next.t("starterSelectUiHandler:useCandies"),
handler: () => {
ui.setMode(Mode.STARTER_SELECT).then(() => showUseCandies());
return true;
@ -939,7 +951,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
});
}
options.push({
label: 'Cancel',
label: i18next.t("menu:cancel"),
handler: () => {
ui.setMode(Mode.STARTER_SELECT);
return true;
@ -1108,17 +1120,17 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
let cycleInstructionLines = [];
if (this.speciesStarterDexEntry?.caughtAttr) {
if (this.canCycleShiny)
cycleInstructionLines.push('R: Cycle Shiny');
cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleShiny"));
if (this.canCycleForm)
cycleInstructionLines.push('F: Cycle Form');
cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleForm"));
if (this.canCycleGender)
cycleInstructionLines.push('G: Cycle Gender');
cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleGender"));
if (this.canCycleAbility)
cycleInstructionLines.push('E: Cycle Ability');
cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleAbility"));
if (this.canCycleNature)
cycleInstructionLines.push('N: Cycle Nature');
cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleNature"));
if (this.canCycleVariant)
cycleInstructionLines.push('V: Cycle Variant');
cycleInstructionLines.push(i18next.t("starterSelectUiHandler:cycleVariant"));
}
if (cycleInstructionLines.length > 2) {
@ -1192,6 +1204,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.shinyIcons[s][v].setTint(getVariantTint(speciesVariants[v] === DexAttr.DEFAULT_VARIANT ? 0 : speciesVariants[v] === DexAttr.VARIANT_2 ? 1 : 2));
}
this.hiddenAbilityIcons[s].setVisible(slotVisible && !!this.scene.gameData.dexData[speciesId].caughtAttr && !!(this.scene.gameData.starterData[speciesId].abilityAttr & 4));
this.classicWinIcons[s].setVisible(slotVisible && this.scene.gameData.starterData[speciesId].classicWinCount > 0);
}
} else {
changed = super.setCursor(cursor);
@ -1697,7 +1710,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.clearText();
};
ui.showText(i18next.t("menu:confirmStartTeam"), null, () => {
ui.showText(i18next.t("starterSelectUiHandler:confirmStartTeam"), null, () => {
ui.setModeWithoutClear(Mode.CONFIRM, () => {
const startRun = (gameMode: GameModes) => {
this.scene.gameMode = gameModes[gameMode];

View File

@ -1,5 +1,5 @@
import { expect, describe, it } from "vitest";
import { randomString } from "./utils";
import { randomString, padInt } from "./utils";
import Phaser from "phaser";
@ -19,4 +19,26 @@ describe("utils", () => {
expect(str1).toBe(str2);
});
});
describe("padInt", () => {
it("should return a string", () => {
const result = padInt(1, 10);
expect(typeof result).toBe('string');
});
it("should return a padded result with default padWith", () => {
const result = padInt(1, 3);
expect(result).toBe('001');
});
it("should return a padded result using a custom padWith", () => {
const result = padInt(1, 10, 'yes')
expect(result).toBe('yesyesyes1');
});
it("should return inputted value when zero length is entered", () => {
const result = padInt(1, 0);
expect(result).toBe('1')
})
});
});

View File

@ -222,7 +222,8 @@ export function executeIf<T>(condition: boolean, promiseFunc: () => Promise<T>):
export const sessionIdKey = 'pokerogue_sessionId';
export const isLocal = window.location.hostname === 'localhost';
export const serverUrl = isLocal ? 'http://localhost:8001' : '';
export const apiUrl = isLocal ? serverUrl : 'api';
export const apiUrl = isLocal ? serverUrl : 'https://api.pokerogue.net';
export const fallbackApiUrl = isLocal ? serverUrl : 'api';
export function setCookie(cName: string, cValue: string): void {
const expiration = new Date();
@ -243,7 +244,7 @@ export function getCookie(cName: string): string {
return '';
}
export function apiFetch(path: string, authed: boolean = false): Promise<Response> {
export function apiFetch(path: string, authed: boolean = false, fallback: boolean = false): Promise<Response> {
return new Promise((resolve, reject) => {
const request = {};
if (authed) {
@ -251,13 +252,22 @@ export function apiFetch(path: string, authed: boolean = false): Promise<Respons
if (sId)
request['headers'] = { 'Authorization': sId };
}
fetch(`${apiUrl}/${path}`, request)
.then(response => resolve(response))
.catch(err => reject(err));
fetch(`${!fallback ? apiUrl : fallbackApiUrl}/${path}`, request)
.then(response => {
if (!response.ok && response.status === 404 && !fallback)
return apiFetch(path, authed, true).then(res => resolve(res));
resolve(response);
})
.catch(err => {
if (fallback)
reject(err);
else
apiFetch(path, authed, true).then(res => resolve(res));
});
});
}
export function apiPost(path: string, data?: any, contentType: string = 'application/json', authed: boolean = false): Promise<Response> {
export function apiPost(path: string, data?: any, contentType: string = 'application/json', authed: boolean = false, fallback: boolean = false): Promise<Response> {
return new Promise((resolve, reject) => {
const headers = {
'Accept': contentType,
@ -268,9 +278,14 @@ export function apiPost(path: string, data?: any, contentType: string = 'applica
if (sId)
headers['Authorization'] = sId;
}
fetch(`${apiUrl}/${path}`, { method: 'POST', headers: headers, body: data })
fetch(`${!fallback ? apiUrl : fallbackApiUrl}/${path}`, { method: 'POST', headers: headers, body: data })
.then(response => resolve(response))
.catch(err => reject(err));
.catch(err => {
if (fallback)
reject(err);
else
apiPost(path, data, contentType, authed, true).then(res => resolve(res));
});
});
}