mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-21 14:59:26 +02:00
pull latest from beta
This commit is contained in:
commit
3211dfa23f
@ -3,4 +3,4 @@ VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=https://apibeta.pokerogue.net
|
||||
VITE_DISCORD_CLIENT_ID=1248062921129459756
|
||||
VITE_GOOGLE_CLIENT_ID=955345393540-2k6lfftf0fdnb0krqmpthjnqavfvvf73.apps.googleusercontent.com
|
||||
VITE_I18N_DEBUG=1
|
||||
VITE_I18N_DEBUG=0
|
||||
|
@ -3,5 +3,5 @@ VITE_BYPASS_TUTORIAL=0
|
||||
VITE_SERVER_URL=http://localhost:8001
|
||||
VITE_DISCORD_CLIENT_ID=1234567890
|
||||
VITE_GOOGLE_CLIENT_ID=1234567890
|
||||
VITE_I18N_DEBUG=1
|
||||
VITE_I18N_DEBUG=0
|
||||
VITE_PORT=8000
|
||||
|
@ -1,9 +1,7 @@
|
||||
/**
|
||||
* This script creates a test boilerplate file for a move or ability.
|
||||
* @param {string} type - The type of test to create. Either "move", "ability",
|
||||
* or "item".
|
||||
* @param {string} fileName - The name of the file to create.
|
||||
* @example npm run create-test move tackle
|
||||
* This script creates a test boilerplate file in the appropriate
|
||||
* directory based on the type selected.
|
||||
* @example npm run create-test
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
@ -34,7 +32,7 @@ async function promptTestType() {
|
||||
console.log("Exiting...");
|
||||
return process.exit();
|
||||
} else if (!typeChoices.includes(typeAnswer.selectedOption)) {
|
||||
console.error('Please provide a valid type ("move", "ability", or "item")!');
|
||||
console.error(`Please provide a valid type (${typeChoices.join(", ")})!`);
|
||||
return await promptTestType();
|
||||
}
|
||||
|
||||
@ -102,7 +100,7 @@ async function runInteractive() {
|
||||
description = `Mystery Encounter - ${formattedName}`;
|
||||
break;
|
||||
default:
|
||||
console.error('Invalid type. Please use "move", "ability", or "item".');
|
||||
console.error(`Invalid type. Please use one of the following: ${typeChoices.join(", ")}.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
BIN
public/images/ui/friendship.png
Normal file
BIN
public/images/ui/friendship.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
BIN
public/images/ui/friendship_overlay.png
Normal file
BIN
public/images/ui/friendship_overlay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 182 B |
BIN
public/images/ui/legacy/friendship.png
Normal file
BIN
public/images/ui/legacy/friendship.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
BIN
public/images/ui/legacy/friendship_overlay.png
Normal file
BIN
public/images/ui/legacy/friendship_overlay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 182 B |
@ -1 +1 @@
|
||||
Subproject commit 005989574fe5638897fa2933b6f57ae4b9c83635
|
||||
Subproject commit 3ccef8472dd7cc7c362538489954cb8fdad27e5f
|
@ -25,7 +25,7 @@ import { trainerConfigs, TrainerSlot } from "./data/trainer-config";
|
||||
import Trainer, { TrainerVariant } from "./field/trainer";
|
||||
import TrainerData from "./system/trainer-data";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { pokemonPrevolutions } from "./data/pokemon-evolutions";
|
||||
import { pokemonPrevolutions } from "./data/balance/pokemon-evolutions";
|
||||
import PokeballTray from "./ui/pokeball-tray";
|
||||
import InvertPostFX from "./pipelines/invert";
|
||||
import { Achv, achvs, ModifierAchv, MoneyAchv } from "./system/achv";
|
||||
@ -42,7 +42,7 @@ import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler"
|
||||
import CharSprite from "./ui/char-sprite";
|
||||
import DamageNumberHandler from "./field/damage-number-handler";
|
||||
import PokemonInfoContainer from "./ui/pokemon-info-container";
|
||||
import { biomeDepths, getBiomeName } from "./data/biomes";
|
||||
import { biomeDepths, getBiomeName } from "./data/balance/biomes";
|
||||
import { SceneBase } from "./scene-base";
|
||||
import CandyBar from "./ui/candy-bar";
|
||||
import { Variant, variantData } from "./data/variant";
|
||||
@ -2445,7 +2445,10 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
success = modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]);
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
success = modifier.apply(pokemon, true);
|
||||
}
|
||||
}
|
||||
if (playSound && !this.sound.get(soundName)) {
|
||||
this.playSound(soundName);
|
||||
@ -2472,7 +2475,7 @@ export default class BattleScene extends SceneBase {
|
||||
for (const p in this.party) {
|
||||
const pokemon = this.party[p];
|
||||
|
||||
const args: any[] = [ pokemon ];
|
||||
const args: unknown[] = [];
|
||||
if (modifier instanceof PokemonHpRestoreModifier) {
|
||||
if (!(modifier as PokemonHpRestoreModifier).fainted) {
|
||||
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
||||
@ -2485,8 +2488,8 @@ export default class BattleScene extends SceneBase {
|
||||
args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon);
|
||||
}
|
||||
|
||||
if (modifier.shouldApply(args)) {
|
||||
const result = modifier.apply(args);
|
||||
if (modifier.shouldApply(pokemon, ...args)) {
|
||||
const result = modifier.apply(pokemon, ...args);
|
||||
if (result instanceof Promise) {
|
||||
modifierPromises.push(result.then(s => success ||= s));
|
||||
} else {
|
||||
@ -2498,8 +2501,8 @@ export default class BattleScene extends SceneBase {
|
||||
return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success));
|
||||
} else {
|
||||
const args = [ this ];
|
||||
if (modifier.shouldApply(args)) {
|
||||
const result = modifier.apply(args);
|
||||
if (modifier.shouldApply(...args)) {
|
||||
const result = modifier.apply(...args);
|
||||
if (result instanceof Promise) {
|
||||
return result.then(success => resolve(success));
|
||||
} else {
|
||||
@ -2521,7 +2524,10 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
if ((modifier as PersistentModifier).add(this.enemyModifiers, false, this)) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]);
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
modifier.apply(pokemon, true);
|
||||
}
|
||||
}
|
||||
for (const rm of modifiersToRemove) {
|
||||
this.removeModifier(rm, true);
|
||||
@ -2755,7 +2761,10 @@ export default class BattleScene extends SceneBase {
|
||||
if (modifierIndex > -1) {
|
||||
modifiers.splice(modifierIndex, 1);
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
modifier.apply([ this.getPokemonById(modifier.pokemonId), false ]);
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
modifier.apply(pokemon, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2773,16 +2782,36 @@ export default class BattleScene extends SceneBase {
|
||||
return (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType);
|
||||
}
|
||||
|
||||
findModifiers(modifierFilter: ModifierPredicate, player: boolean = true): PersistentModifier[] {
|
||||
return (player ? this.modifiers : this.enemyModifiers).filter(m => (modifierFilter as ModifierPredicate)(m));
|
||||
/**
|
||||
* Get all of the modifiers that pass the `modifierFilter` function
|
||||
* @param modifierFilter The function used to filter a target's modifiers
|
||||
* @param isPlayer Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @returns the list of all modifiers that passed the `modifierFilter` function
|
||||
*/
|
||||
findModifiers(modifierFilter: ModifierPredicate, isPlayer: boolean = true): PersistentModifier[] {
|
||||
return (isPlayer ? this.modifiers : this.enemyModifiers).filter(modifierFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first modifier that pass the `modifierFilter` function
|
||||
* @param modifierFilter The function used to filter a target's modifiers
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @returns the first modifier that passed the `modifierFilter` function; `undefined` if none passed
|
||||
*/
|
||||
findModifier(modifierFilter: ModifierPredicate, player: boolean = true): PersistentModifier | undefined {
|
||||
return (player ? this.modifiers : this.enemyModifiers).find(m => (modifierFilter as ModifierPredicate)(m));
|
||||
return (player ? this.modifiers : this.enemyModifiers).find(modifierFilter);
|
||||
}
|
||||
|
||||
applyShuffledModifiers(scene: BattleScene, modifierType: Constructor<Modifier>, player: boolean = true, ...args: any[]): PersistentModifier[] {
|
||||
let modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args));
|
||||
/**
|
||||
* Apply all modifiers that match `modifierType` in a random order
|
||||
* @param scene {@linkcode BattleScene} used to randomize the order of modifiers
|
||||
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @param ...args The list of arguments needed to invoke `modifierType.apply`
|
||||
* @returns the list of all modifiers that matched `modifierType` and were applied.
|
||||
*/
|
||||
applyShuffledModifiers<T extends PersistentModifier>(scene: BattleScene, modifierType: Constructor<T>, player: boolean = true, ...args: Parameters<T["apply"]>): T[] {
|
||||
let modifiers = (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType && m.shouldApply(...args));
|
||||
scene.executeWithSeedOffset(() => {
|
||||
const shuffleModifiers = mods => {
|
||||
if (mods.length < 1) {
|
||||
@ -2796,15 +2825,23 @@ export default class BattleScene extends SceneBase {
|
||||
return this.applyModifiersInternal(modifiers, player, args);
|
||||
}
|
||||
|
||||
applyModifiers(modifierType: Constructor<Modifier>, player: boolean = true, ...args: any[]): PersistentModifier[] {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args));
|
||||
/**
|
||||
* Apply all modifiers that match `modifierType`
|
||||
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @param ...args The list of arguments needed to invoke `modifierType.apply`
|
||||
* @returns the list of all modifiers that matched `modifierType` and were applied.
|
||||
*/
|
||||
applyModifiers<T extends PersistentModifier>(modifierType: Constructor<T>, player: boolean = true, ...args: Parameters<T["apply"]>): T[] {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType && m.shouldApply(...args));
|
||||
return this.applyModifiersInternal(modifiers, player, args);
|
||||
}
|
||||
|
||||
applyModifiersInternal(modifiers: PersistentModifier[], player: boolean, args: any[]): PersistentModifier[] {
|
||||
const appliedModifiers: PersistentModifier[] = [];
|
||||
/** Helper function to apply all passed modifiers */
|
||||
applyModifiersInternal<T extends PersistentModifier>(modifiers: T[], player: boolean, args: Parameters<T["apply"]>): T[] {
|
||||
const appliedModifiers: T[] = [];
|
||||
for (const modifier of modifiers) {
|
||||
if (modifier.apply(args)) {
|
||||
if (modifier.apply(...args)) {
|
||||
console.log("Applied", modifier.type.name, !player ? "(enemy)" : "");
|
||||
appliedModifiers.push(modifier);
|
||||
}
|
||||
@ -2813,10 +2850,17 @@ export default class BattleScene extends SceneBase {
|
||||
return appliedModifiers;
|
||||
}
|
||||
|
||||
applyModifier(modifierType: Constructor<Modifier>, player: boolean = true, ...args: any[]): PersistentModifier | null {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args));
|
||||
/**
|
||||
* Apply the first modifier that matches `modifierType`
|
||||
* @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier}
|
||||
* @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true`
|
||||
* @param ...args The list of arguments needed to invoke `modifierType.apply`
|
||||
* @returns the first modifier that matches `modifierType` and was applied; return `null` if none matched
|
||||
*/
|
||||
applyModifier<T extends PersistentModifier>(modifierType: Constructor<T>, player: boolean = true, ...args: Parameters<T["apply"]>): T | null {
|
||||
const modifiers = (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType && m.shouldApply(...args));
|
||||
for (const modifier of modifiers) {
|
||||
if (modifier.apply(args)) {
|
||||
if (modifier.apply(...args)) {
|
||||
console.log("Applied", modifier.type.name, !player ? "(enemy)" : "");
|
||||
return modifier;
|
||||
}
|
||||
@ -2882,7 +2926,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
validateAchv(achv: Achv, args?: any[]): boolean {
|
||||
validateAchv(achv: Achv, args?: unknown[]): boolean {
|
||||
if (!this.gameData.achvUnlocks.hasOwnProperty(achv.id) && achv.validate(this, args)) {
|
||||
this.gameData.achvUnlocks[achv.id] = new Date().getTime();
|
||||
this.ui.achvBar.showAchv(achv);
|
||||
@ -2895,7 +2939,7 @@ export default class BattleScene extends SceneBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
validateVoucher(voucher: Voucher, args?: any[]): boolean {
|
||||
validateVoucher(voucher: Voucher, args?: unknown[]): boolean {
|
||||
if (!this.gameData.voucherUnlocks.hasOwnProperty(voucher.id) && voucher.validate(this, args)) {
|
||||
this.gameData.voucherUnlocks[voucher.id] = new Date().getTime();
|
||||
this.ui.achvBar.showAchv(voucher);
|
||||
|
@ -519,6 +519,7 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr {
|
||||
|
||||
if (pokemon.isFullHp() && typeMultiplier.value > 0.5) {
|
||||
typeMultiplier.value = 0.5;
|
||||
pokemon.turnData.moveEffectiveness = 0.5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Type } from "./type";
|
||||
import * as Utils from "../utils";
|
||||
import { pokemonEvolutions, SpeciesFormEvolution } from "./pokemon-evolutions";
|
||||
import { Type } from "#app/data/type";
|
||||
import * as Utils from "#app/utils";
|
||||
import { pokemonEvolutions, SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||
import i18next from "i18next";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Species } from "#enums/species";
|
@ -1,5 +1,5 @@
|
||||
import { allMoves } from "./move";
|
||||
import * as Utils from "../utils";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import * as Utils from "#app/utils";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
|
574
src/data/balance/passives.ts
Normal file
574
src/data/balance/passives.ts
Normal file
@ -0,0 +1,574 @@
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Species } from "#app/enums/species";
|
||||
|
||||
export const starterPassiveAbilities = {
|
||||
[Species.BULBASAUR]: Abilities.GRASSY_SURGE,
|
||||
[Species.CHARMANDER]: Abilities.BEAST_BOOST,
|
||||
[Species.SQUIRTLE]: Abilities.STURDY,
|
||||
[Species.CATERPIE]: Abilities.MAGICIAN,
|
||||
[Species.WEEDLE]: Abilities.TINTED_LENS,
|
||||
[Species.PIDGEY]: Abilities.SHEER_FORCE,
|
||||
[Species.RATTATA]: Abilities.STRONG_JAW,
|
||||
[Species.SPEAROW]: Abilities.MOXIE,
|
||||
[Species.EKANS]: Abilities.REGENERATOR,
|
||||
[Species.SANDSHREW]: Abilities.TOUGH_CLAWS,
|
||||
[Species.NIDORAN_F]: Abilities.FLARE_BOOST,
|
||||
[Species.NIDORAN_M]: Abilities.GUTS,
|
||||
[Species.VULPIX]: Abilities.FUR_COAT,
|
||||
[Species.ZUBAT]: Abilities.INTIMIDATE,
|
||||
[Species.ODDISH]: Abilities.TRIAGE,
|
||||
[Species.PARAS]: Abilities.TRIAGE,
|
||||
[Species.VENONAT]: Abilities.SIMPLE,
|
||||
[Species.DIGLETT]: Abilities.STURDY,
|
||||
[Species.MEOWTH]: Abilities.TOUGH_CLAWS,
|
||||
[Species.PSYDUCK]: Abilities.SIMPLE,
|
||||
[Species.MANKEY]: Abilities.IRON_FIST,
|
||||
[Species.GROWLITHE]: Abilities.SPEED_BOOST,
|
||||
[Species.POLIWAG]: Abilities.NO_GUARD,
|
||||
[Species.ABRA]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.MACHOP]: Abilities.QUICK_FEET,
|
||||
[Species.BELLSPROUT]: Abilities.FLOWER_GIFT,
|
||||
[Species.TENTACOOL]: Abilities.TOXIC_CHAIN,
|
||||
[Species.GEODUDE]: Abilities.DRY_SKIN,
|
||||
[Species.PONYTA]: Abilities.MAGIC_GUARD,
|
||||
[Species.SLOWPOKE]: Abilities.UNAWARE,
|
||||
[Species.MAGNEMITE]: Abilities.LEVITATE,
|
||||
[Species.FARFETCHD]: Abilities.SNIPER,
|
||||
[Species.DODUO]: Abilities.PARENTAL_BOND,
|
||||
[Species.SEEL]: Abilities.WATER_BUBBLE,
|
||||
[Species.GRIMER]: Abilities.WATER_ABSORB,
|
||||
[Species.SHELLDER]: Abilities.ICE_SCALES,
|
||||
[Species.GASTLY]: Abilities.SHADOW_SHIELD,
|
||||
[Species.ONIX]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.DROWZEE]: Abilities.MAGICIAN,
|
||||
[Species.KRABBY]: Abilities.THERMAL_EXCHANGE,
|
||||
[Species.VOLTORB]: Abilities.TRANSISTOR,
|
||||
[Species.EXEGGCUTE]: Abilities.RIPEN,
|
||||
[Species.CUBONE]: Abilities.PARENTAL_BOND,
|
||||
[Species.LICKITUNG]: Abilities.CHEEK_POUCH,
|
||||
[Species.KOFFING]: Abilities.PARENTAL_BOND,
|
||||
[Species.RHYHORN]: Abilities.FILTER,
|
||||
[Species.TANGELA]: Abilities.SEED_SOWER,
|
||||
[Species.KANGASKHAN]: Abilities.GUTS,
|
||||
[Species.HORSEA]: Abilities.DRAGONS_MAW,
|
||||
[Species.GOLDEEN]: Abilities.MULTISCALE,
|
||||
[Species.STARYU]: Abilities.REGENERATOR,
|
||||
[Species.SCYTHER]: Abilities.TINTED_LENS,
|
||||
[Species.PINSIR]: Abilities.TINTED_LENS,
|
||||
[Species.TAUROS]: Abilities.STAMINA,
|
||||
[Species.MAGIKARP]: Abilities.MULTISCALE,
|
||||
[Species.LAPRAS]: Abilities.LIGHTNING_ROD,
|
||||
[Species.DITTO]: Abilities.ADAPTABILITY,
|
||||
[Species.EEVEE]: Abilities.PICKUP,
|
||||
[Species.PORYGON]: Abilities.PROTEAN,
|
||||
[Species.OMANYTE]: Abilities.STURDY,
|
||||
[Species.KABUTO]: Abilities.TOUGH_CLAWS,
|
||||
[Species.AERODACTYL]: Abilities.ORICHALCUM_PULSE,
|
||||
[Species.ARTICUNO]: Abilities.SNOW_WARNING,
|
||||
[Species.ZAPDOS]: Abilities.DRIZZLE,
|
||||
[Species.MOLTRES]: Abilities.DROUGHT,
|
||||
[Species.DRATINI]: Abilities.AERILATE,
|
||||
[Species.MEWTWO]: Abilities.NEUROFORCE,
|
||||
[Species.MEW]: Abilities.PROTEAN,
|
||||
[Species.CHIKORITA]: Abilities.THICK_FAT,
|
||||
[Species.CYNDAQUIL]: Abilities.DROUGHT,
|
||||
[Species.TOTODILE]: Abilities.TOUGH_CLAWS,
|
||||
[Species.SENTRET]: Abilities.PICKUP,
|
||||
[Species.HOOTHOOT]: Abilities.AERILATE,
|
||||
[Species.LEDYBA]: Abilities.PRANKSTER,
|
||||
[Species.SPINARAK]: Abilities.PRANKSTER,
|
||||
[Species.CHINCHOU]: Abilities.WATER_BUBBLE,
|
||||
[Species.PICHU]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.CLEFFA]: Abilities.ANALYTIC,
|
||||
[Species.IGGLYBUFF]: Abilities.HUGE_POWER,
|
||||
[Species.TOGEPI]: Abilities.PIXILATE,
|
||||
[Species.NATU]: Abilities.TINTED_LENS,
|
||||
[Species.MAREEP]: Abilities.ELECTROMORPHOSIS,
|
||||
[Species.HOPPIP]: Abilities.FLUFFY,
|
||||
[Species.AIPOM]: Abilities.SCRAPPY,
|
||||
[Species.SUNKERN]: Abilities.DROUGHT,
|
||||
[Species.YANMA]: Abilities.SHEER_FORCE,
|
||||
[Species.WOOPER]: Abilities.COMATOSE,
|
||||
[Species.MURKROW]: Abilities.DARK_AURA,
|
||||
[Species.MISDREAVUS]: Abilities.BEADS_OF_RUIN,
|
||||
[Species.UNOWN]: Abilities.PICKUP,
|
||||
[Species.GIRAFARIG]: Abilities.PARENTAL_BOND,
|
||||
[Species.PINECO]: Abilities.IRON_BARBS,
|
||||
[Species.DUNSPARCE]: Abilities.UNAWARE,
|
||||
[Species.GLIGAR]: Abilities.TOXIC_BOOST,
|
||||
[Species.SNUBBULL]: Abilities.PIXILATE,
|
||||
[Species.QWILFISH]: Abilities.TOXIC_DEBRIS,
|
||||
[Species.SHUCKLE]: Abilities.HARVEST,
|
||||
[Species.HERACROSS]: Abilities.TECHNICIAN,
|
||||
[Species.SNEASEL]: Abilities.TOUGH_CLAWS,
|
||||
[Species.TEDDIURSA]: Abilities.THICK_FAT,
|
||||
[Species.SLUGMA]: Abilities.DESOLATE_LAND,
|
||||
[Species.SWINUB]: Abilities.SLUSH_RUSH,
|
||||
[Species.CORSOLA]: Abilities.STORM_DRAIN,
|
||||
[Species.REMORAID]: Abilities.SIMPLE,
|
||||
[Species.DELIBIRD]: Abilities.HUGE_POWER,
|
||||
[Species.SKARMORY]: Abilities.LIGHTNING_ROD,
|
||||
[Species.HOUNDOUR]: Abilities.DROUGHT,
|
||||
[Species.PHANPY]: Abilities.SPEED_BOOST,
|
||||
[Species.STANTLER]: Abilities.SPEED_BOOST,
|
||||
[Species.SMEARGLE]: Abilities.PRANKSTER,
|
||||
[Species.TYROGUE]: Abilities.MOXIE,
|
||||
[Species.SMOOCHUM]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.ELEKID]: Abilities.SHEER_FORCE,
|
||||
[Species.MAGBY]: Abilities.CONTRARY,
|
||||
[Species.MILTANK]: Abilities.STAMINA,
|
||||
[Species.RAIKOU]: Abilities.TRANSISTOR,
|
||||
[Species.ENTEI]: Abilities.MOXIE,
|
||||
[Species.SUICUNE]: Abilities.UNAWARE,
|
||||
[Species.LARVITAR]: Abilities.SAND_RUSH,
|
||||
[Species.LUGIA]: Abilities.DELTA_STREAM,
|
||||
[Species.HO_OH]: Abilities.MAGIC_GUARD,
|
||||
[Species.CELEBI]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.TREECKO]: Abilities.TINTED_LENS,
|
||||
[Species.TORCHIC]: Abilities.RECKLESS,
|
||||
[Species.MUDKIP]: Abilities.DRIZZLE,
|
||||
[Species.POOCHYENA]: Abilities.TOUGH_CLAWS,
|
||||
[Species.ZIGZAGOON]: Abilities.RUN_AWAY,
|
||||
[Species.WURMPLE]: Abilities.SIMPLE,
|
||||
[Species.LOTAD]: Abilities.DRIZZLE,
|
||||
[Species.SEEDOT]: Abilities.SHARPNESS,
|
||||
[Species.TAILLOW]: Abilities.AERILATE,
|
||||
[Species.WINGULL]: Abilities.SWIFT_SWIM,
|
||||
[Species.RALTS]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.SURSKIT]: Abilities.WATER_BUBBLE,
|
||||
[Species.SHROOMISH]: Abilities.GUTS,
|
||||
[Species.SLAKOTH]: Abilities.GUTS,
|
||||
[Species.NINCADA]: Abilities.MAGIC_GUARD,
|
||||
[Species.WHISMUR]: Abilities.PUNK_ROCK,
|
||||
[Species.MAKUHITA]: Abilities.STAMINA,
|
||||
[Species.AZURILL]: Abilities.MISTY_SURGE,
|
||||
[Species.NOSEPASS]: Abilities.LEVITATE,
|
||||
[Species.SKITTY]: Abilities.SCRAPPY,
|
||||
[Species.SABLEYE]: Abilities.UNNERVE,
|
||||
[Species.MAWILE]: Abilities.UNNERVE,
|
||||
[Species.ARON]: Abilities.EARTH_EATER,
|
||||
[Species.MEDITITE]: Abilities.MINDS_EYE,
|
||||
[Species.ELECTRIKE]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.PLUSLE]: Abilities.POWER_SPOT,
|
||||
[Species.MINUN]: Abilities.POWER_SPOT,
|
||||
[Species.VOLBEAT]: Abilities.HONEY_GATHER,
|
||||
[Species.ILLUMISE]: Abilities.HONEY_GATHER,
|
||||
[Species.GULPIN]: Abilities.EARTH_EATER,
|
||||
[Species.CARVANHA]: Abilities.SHEER_FORCE,
|
||||
[Species.WAILMER]: Abilities.LEVITATE,
|
||||
[Species.NUMEL]: Abilities.FUR_COAT,
|
||||
[Species.TORKOAL]: Abilities.ANALYTIC,
|
||||
[Species.SPOINK]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.SPINDA]: Abilities.SIMPLE,
|
||||
[Species.TRAPINCH]: Abilities.ADAPTABILITY,
|
||||
[Species.CACNEA]: Abilities.SAND_RUSH,
|
||||
[Species.SWABLU]: Abilities.ADAPTABILITY,
|
||||
[Species.ZANGOOSE]: Abilities.POISON_HEAL,
|
||||
[Species.SEVIPER]: Abilities.MULTISCALE,
|
||||
[Species.LUNATONE]: Abilities.SHADOW_SHIELD,
|
||||
[Species.SOLROCK]: Abilities.DROUGHT,
|
||||
[Species.BARBOACH]: Abilities.SIMPLE,
|
||||
[Species.CORPHISH]: Abilities.TOUGH_CLAWS,
|
||||
[Species.BALTOY]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.LILEEP]: Abilities.SEED_SOWER,
|
||||
[Species.ANORITH]: Abilities.WATER_ABSORB,
|
||||
[Species.FEEBAS]: Abilities.MAGIC_GUARD,
|
||||
[Species.CASTFORM]: Abilities.ADAPTABILITY,
|
||||
[Species.KECLEON]: Abilities.ADAPTABILITY,
|
||||
[Species.SHUPPET]: Abilities.SHADOW_SHIELD,
|
||||
[Species.DUSKULL]: Abilities.UNNERVE,
|
||||
[Species.TROPIUS]: Abilities.RIPEN,
|
||||
[Species.ABSOL]: Abilities.SHARPNESS,
|
||||
[Species.WYNAUT]: Abilities.STURDY,
|
||||
[Species.SNORUNT]: Abilities.SNOW_WARNING,
|
||||
[Species.SPHEAL]: Abilities.UNAWARE,
|
||||
[Species.CLAMPERL]: Abilities.DRIZZLE,
|
||||
[Species.RELICANTH]: Abilities.PRIMORDIAL_SEA,
|
||||
[Species.LUVDISC]: Abilities.MULTISCALE,
|
||||
[Species.BAGON]: Abilities.DRAGONS_MAW,
|
||||
[Species.BELDUM]: Abilities.LEVITATE,
|
||||
[Species.REGIROCK]: Abilities.SAND_STREAM,
|
||||
[Species.REGICE]: Abilities.SNOW_WARNING,
|
||||
[Species.REGISTEEL]: Abilities.FILTER,
|
||||
[Species.LATIAS]: Abilities.PRISM_ARMOR,
|
||||
[Species.LATIOS]: Abilities.TINTED_LENS,
|
||||
[Species.KYOGRE]: Abilities.MOLD_BREAKER,
|
||||
[Species.GROUDON]: Abilities.TURBOBLAZE,
|
||||
[Species.RAYQUAZA]: Abilities.UNNERVE,
|
||||
[Species.JIRACHI]: Abilities.COMATOSE,
|
||||
[Species.DEOXYS]: Abilities.PROTEAN,
|
||||
[Species.TURTWIG]: Abilities.THICK_FAT,
|
||||
[Species.CHIMCHAR]: Abilities.BEAST_BOOST,
|
||||
[Species.PIPLUP]: Abilities.DRIZZLE,
|
||||
[Species.STARLY]: Abilities.ROCK_HEAD,
|
||||
[Species.BIDOOF]: Abilities.SAP_SIPPER,
|
||||
[Species.KRICKETOT]: Abilities.SHARPNESS,
|
||||
[Species.SHINX]: Abilities.SPEED_BOOST,
|
||||
[Species.BUDEW]: Abilities.GRASSY_SURGE,
|
||||
[Species.CRANIDOS]: Abilities.ROCK_HEAD,
|
||||
[Species.SHIELDON]: Abilities.EARTH_EATER,
|
||||
[Species.BURMY]: Abilities.STURDY,
|
||||
[Species.COMBEE]: Abilities.INTIMIDATE,
|
||||
[Species.PACHIRISU]: Abilities.HONEY_GATHER,
|
||||
[Species.BUIZEL]: Abilities.MOXIE,
|
||||
[Species.CHERUBI]: Abilities.ORICHALCUM_PULSE,
|
||||
[Species.SHELLOS]: Abilities.REGENERATOR,
|
||||
[Species.DRIFLOON]: Abilities.MAGIC_GUARD,
|
||||
[Species.BUNEARY]: Abilities.ADAPTABILITY,
|
||||
[Species.GLAMEOW]: Abilities.INTIMIDATE,
|
||||
[Species.CHINGLING]: Abilities.PUNK_ROCK,
|
||||
[Species.STUNKY]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.BRONZOR]: Abilities.BULLETPROOF,
|
||||
[Species.BONSLY]: Abilities.SAP_SIPPER,
|
||||
[Species.MIME_JR]: Abilities.OPPORTUNIST,
|
||||
[Species.HAPPINY]: Abilities.FUR_COAT,
|
||||
[Species.CHATOT]: Abilities.PUNK_ROCK,
|
||||
[Species.SPIRITOMB]: Abilities.VESSEL_OF_RUIN,
|
||||
[Species.GIBLE]: Abilities.SAND_STREAM,
|
||||
[Species.MUNCHLAX]: Abilities.RIPEN,
|
||||
[Species.RIOLU]: Abilities.MINDS_EYE,
|
||||
[Species.HIPPOPOTAS]: Abilities.UNAWARE,
|
||||
[Species.SKORUPI]: Abilities.SUPER_LUCK,
|
||||
[Species.CROAGUNK]: Abilities.MOXIE,
|
||||
[Species.CARNIVINE]: Abilities.ARENA_TRAP,
|
||||
[Species.FINNEON]: Abilities.WATER_BUBBLE,
|
||||
[Species.MANTYKE]: Abilities.UNAWARE,
|
||||
[Species.SNOVER]: Abilities.THICK_FAT,
|
||||
[Species.ROTOM]: Abilities.HADRON_ENGINE,
|
||||
[Species.UXIE]: Abilities.UNAWARE,
|
||||
[Species.MESPRIT]: Abilities.MOODY,
|
||||
[Species.AZELF]: Abilities.NEUROFORCE,
|
||||
[Species.DIALGA]: Abilities.LEVITATE,
|
||||
[Species.PALKIA]: Abilities.SPEED_BOOST,
|
||||
[Species.HEATRAN]: Abilities.EARTH_EATER,
|
||||
[Species.REGIGIGAS]: Abilities.SCRAPPY,
|
||||
[Species.GIRATINA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.CRESSELIA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.PHIONE]: Abilities.SIMPLE,
|
||||
[Species.MANAPHY]: Abilities.PRIMORDIAL_SEA,
|
||||
[Species.DARKRAI]: Abilities.UNNERVE,
|
||||
[Species.SHAYMIN]: Abilities.WIND_RIDER,
|
||||
[Species.ARCEUS]: Abilities.ADAPTABILITY,
|
||||
[Species.VICTINI]: Abilities.SHEER_FORCE,
|
||||
[Species.SNIVY]: Abilities.MULTISCALE,
|
||||
[Species.TEPIG]: Abilities.ROCK_HEAD,
|
||||
[Species.OSHAWOTT]: Abilities.INTREPID_SWORD,
|
||||
[Species.PATRAT]: Abilities.NO_GUARD,
|
||||
[Species.LILLIPUP]: Abilities.FUR_COAT,
|
||||
[Species.PURRLOIN]: Abilities.PICKUP,
|
||||
[Species.PANSAGE]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.PANSEAR]: Abilities.WATER_ABSORB,
|
||||
[Species.PANPOUR]: Abilities.SAP_SIPPER,
|
||||
[Species.MUNNA]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.PIDOVE]: Abilities.SNIPER,
|
||||
[Species.BLITZLE]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.ROGGENROLA]: Abilities.SOLID_ROCK,
|
||||
[Species.WOOBAT]: Abilities.OPPORTUNIST,
|
||||
[Species.DRILBUR]: Abilities.SAND_STREAM,
|
||||
[Species.AUDINO]: Abilities.FRIEND_GUARD,
|
||||
[Species.TIMBURR]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.TYMPOLE]: Abilities.POISON_HEAL,
|
||||
[Species.THROH]: Abilities.STAMINA,
|
||||
[Species.SAWK]: Abilities.SCRAPPY,
|
||||
[Species.SEWADDLE]: Abilities.SHARPNESS,
|
||||
[Species.VENIPEDE]: Abilities.STAMINA,
|
||||
[Species.COTTONEE]: Abilities.FLUFFY,
|
||||
[Species.PETILIL]: Abilities.SIMPLE,
|
||||
[Species.BASCULIN]: Abilities.SUPREME_OVERLORD,
|
||||
[Species.SANDILE]: Abilities.TOUGH_CLAWS,
|
||||
[Species.DARUMAKA]: Abilities.GORILLA_TACTICS,
|
||||
[Species.MARACTUS]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.DWEBBLE]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.SCRAGGY]: Abilities.PROTEAN,
|
||||
[Species.SIGILYPH]: Abilities.FLARE_BOOST,
|
||||
[Species.YAMASK]: Abilities.PURIFYING_SALT,
|
||||
[Species.TIRTOUGA]: Abilities.WATER_ABSORB,
|
||||
[Species.ARCHEN]: Abilities.MULTISCALE,
|
||||
[Species.TRUBBISH]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.ZORUA]: Abilities.DARK_AURA,
|
||||
[Species.MINCCINO]: Abilities.FUR_COAT,
|
||||
[Species.GOTHITA]: Abilities.UNNERVE,
|
||||
[Species.SOLOSIS]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.DUCKLETT]: Abilities.DRIZZLE,
|
||||
[Species.VANILLITE]: Abilities.SLUSH_RUSH,
|
||||
[Species.DEERLING]: Abilities.FUR_COAT,
|
||||
[Species.EMOLGA]: Abilities.TRANSISTOR,
|
||||
[Species.KARRABLAST]: Abilities.QUICK_DRAW,
|
||||
[Species.FOONGUS]: Abilities.THICK_FAT,
|
||||
[Species.FRILLISH]: Abilities.POISON_HEAL,
|
||||
[Species.ALOMOMOLA]: Abilities.MULTISCALE,
|
||||
[Species.JOLTIK]: Abilities.TRANSISTOR,
|
||||
[Species.FERROSEED]: Abilities.ROUGH_SKIN,
|
||||
[Species.KLINK]: Abilities.STEELY_SPIRIT,
|
||||
[Species.TYNAMO]: Abilities.POISON_HEAL,
|
||||
[Species.ELGYEM]: Abilities.PRISM_ARMOR,
|
||||
[Species.LITWICK]: Abilities.SOUL_HEART,
|
||||
[Species.AXEW]: Abilities.DRAGONS_MAW,
|
||||
[Species.CUBCHOO]: Abilities.TOUGH_CLAWS,
|
||||
[Species.CRYOGONAL]: Abilities.SNOW_WARNING,
|
||||
[Species.SHELMET]: Abilities.PROTEAN,
|
||||
[Species.STUNFISK]: Abilities.STORM_DRAIN,
|
||||
[Species.MIENFOO]: Abilities.NO_GUARD,
|
||||
[Species.DRUDDIGON]: Abilities.INTIMIDATE,
|
||||
[Species.GOLETT]: Abilities.SHADOW_SHIELD,
|
||||
[Species.PAWNIARD]: Abilities.SWORD_OF_RUIN,
|
||||
[Species.BOUFFALANT]: Abilities.ROCK_HEAD,
|
||||
[Species.RUFFLET]: Abilities.SPEED_BOOST,
|
||||
[Species.VULLABY]: Abilities.THICK_FAT,
|
||||
[Species.HEATMOR]: Abilities.CONTRARY,
|
||||
[Species.DURANT]: Abilities.COMPOUND_EYES,
|
||||
[Species.DEINO]: Abilities.PARENTAL_BOND,
|
||||
[Species.LARVESTA]: Abilities.DROUGHT,
|
||||
[Species.COBALION]: Abilities.INTREPID_SWORD,
|
||||
[Species.TERRAKION]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.VIRIZION]: Abilities.SHARPNESS,
|
||||
[Species.TORNADUS]: Abilities.DRIZZLE,
|
||||
[Species.THUNDURUS]: Abilities.DRIZZLE,
|
||||
[Species.RESHIRAM]: Abilities.ORICHALCUM_PULSE,
|
||||
[Species.ZEKROM]: Abilities.HADRON_ENGINE,
|
||||
[Species.LANDORUS]: Abilities.STORM_DRAIN,
|
||||
[Species.KYUREM]: Abilities.SNOW_WARNING,
|
||||
[Species.KELDEO]: Abilities.GRIM_NEIGH,
|
||||
[Species.MELOETTA]: Abilities.MINDS_EYE,
|
||||
[Species.GENESECT]: Abilities.PROTEAN,
|
||||
[Species.CHESPIN]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.FENNEKIN]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.FROAKIE]: Abilities.STAKEOUT,
|
||||
[Species.BUNNELBY]: Abilities.GUTS,
|
||||
[Species.FLETCHLING]: Abilities.MAGIC_GUARD,
|
||||
[Species.SCATTERBUG]: Abilities.PRANKSTER,
|
||||
[Species.LITLEO]: Abilities.BEAST_BOOST,
|
||||
[Species.FLABEBE]: Abilities.GRASSY_SURGE,
|
||||
[Species.SKIDDO]: Abilities.SEED_SOWER,
|
||||
[Species.PANCHAM]: Abilities.FUR_COAT,
|
||||
[Species.FURFROU]: Abilities.FLUFFY,
|
||||
[Species.ESPURR]: Abilities.FUR_COAT,
|
||||
[Species.HONEDGE]: Abilities.SHARPNESS,
|
||||
[Species.SPRITZEE]: Abilities.FUR_COAT,
|
||||
[Species.SWIRLIX]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.INKAY]: Abilities.UNNERVE,
|
||||
[Species.BINACLE]: Abilities.SAP_SIPPER,
|
||||
[Species.SKRELP]: Abilities.DRAGONS_MAW,
|
||||
[Species.CLAUNCHER]: Abilities.SWIFT_SWIM,
|
||||
[Species.HELIOPTILE]: Abilities.PROTEAN,
|
||||
[Species.TYRUNT]: Abilities.RECKLESS,
|
||||
[Species.AMAURA]: Abilities.ICE_SCALES,
|
||||
[Species.HAWLUCHA]: Abilities.MOXIE,
|
||||
[Species.DEDENNE]: Abilities.PIXILATE,
|
||||
[Species.CARBINK]: Abilities.SOLID_ROCK,
|
||||
[Species.GOOMY]: Abilities.REGENERATOR,
|
||||
[Species.KLEFKI]: Abilities.LEVITATE,
|
||||
[Species.PHANTUMP]: Abilities.SHADOW_TAG,
|
||||
[Species.PUMPKABOO]: Abilities.WELL_BAKED_BODY,
|
||||
[Species.BERGMITE]: Abilities.ICE_SCALES,
|
||||
[Species.NOIBAT]: Abilities.PUNK_ROCK,
|
||||
[Species.XERNEAS]: Abilities.HARVEST,
|
||||
[Species.YVELTAL]: Abilities.SOUL_HEART,
|
||||
[Species.ZYGARDE]: Abilities.HUGE_POWER,
|
||||
[Species.DIANCIE]: Abilities.LEVITATE,
|
||||
[Species.HOOPA]: Abilities.OPPORTUNIST,
|
||||
[Species.VOLCANION]: Abilities.FILTER,
|
||||
[Species.ROWLET]: Abilities.SNIPER,
|
||||
[Species.LITTEN]: Abilities.OPPORTUNIST,
|
||||
[Species.POPPLIO]: Abilities.PUNK_ROCK,
|
||||
[Species.PIKIPEK]: Abilities.TECHNICIAN,
|
||||
[Species.YUNGOOS]: Abilities.TOUGH_CLAWS,
|
||||
[Species.GRUBBIN]: Abilities.SPEED_BOOST,
|
||||
[Species.CRABRAWLER]: Abilities.WATER_BUBBLE,
|
||||
[Species.ORICORIO]: Abilities.ADAPTABILITY,
|
||||
[Species.CUTIEFLY]: Abilities.TINTED_LENS,
|
||||
[Species.ROCKRUFF]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.WISHIWASHI]: Abilities.REGENERATOR,
|
||||
[Species.MAREANIE]: Abilities.TOXIC_DEBRIS,
|
||||
[Species.MUDBRAY]: Abilities.CUD_CHEW,
|
||||
[Species.DEWPIDER]: Abilities.TINTED_LENS,
|
||||
[Species.FOMANTIS]: Abilities.SHARPNESS,
|
||||
[Species.MORELULL]: Abilities.TRIAGE,
|
||||
[Species.SALANDIT]: Abilities.DRAGONS_MAW,
|
||||
[Species.STUFFUL]: Abilities.SCRAPPY,
|
||||
[Species.BOUNSWEET]: Abilities.MOXIE,
|
||||
[Species.COMFEY]: Abilities.FRIEND_GUARD,
|
||||
[Species.ORANGURU]: Abilities.POWER_SPOT,
|
||||
[Species.PASSIMIAN]: Abilities.LIBERO,
|
||||
[Species.WIMPOD]: Abilities.REGENERATOR,
|
||||
[Species.SANDYGAST]: Abilities.SAND_SPIT,
|
||||
[Species.PYUKUMUKU]: Abilities.PURIFYING_SALT,
|
||||
[Species.TYPE_NULL]: Abilities.ADAPTABILITY,
|
||||
[Species.MINIOR]: Abilities.STURDY,
|
||||
[Species.KOMALA]: Abilities.GUTS,
|
||||
[Species.TURTONATOR]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.TOGEDEMARU]: Abilities.ROUGH_SKIN,
|
||||
[Species.MIMIKYU]: Abilities.TOUGH_CLAWS,
|
||||
[Species.BRUXISH]: Abilities.MULTISCALE,
|
||||
[Species.DRAMPA]: Abilities.THICK_FAT,
|
||||
[Species.DHELMISE]: Abilities.WATER_BUBBLE,
|
||||
[Species.JANGMO_O]: Abilities.DAUNTLESS_SHIELD,
|
||||
[Species.TAPU_KOKO]: Abilities.TRANSISTOR,
|
||||
[Species.TAPU_LELE]: Abilities.SHEER_FORCE,
|
||||
[Species.TAPU_BULU]: Abilities.TRIAGE,
|
||||
[Species.TAPU_FINI]: Abilities.FAIRY_AURA,
|
||||
[Species.COSMOG]: Abilities.BEAST_BOOST,
|
||||
[Species.NIHILEGO]: Abilities.LEVITATE,
|
||||
[Species.BUZZWOLE]: Abilities.MOXIE,
|
||||
[Species.PHEROMOSA]: Abilities.TINTED_LENS,
|
||||
[Species.XURKITREE]: Abilities.TRANSISTOR,
|
||||
[Species.CELESTEELA]: Abilities.HEATPROOF,
|
||||
[Species.KARTANA]: Abilities.SHARPNESS,
|
||||
[Species.GUZZLORD]: Abilities.POISON_HEAL,
|
||||
[Species.NECROZMA]: Abilities.BEAST_BOOST,
|
||||
[Species.MAGEARNA]: Abilities.STEELY_SPIRIT,
|
||||
[Species.MARSHADOW]: Abilities.IRON_FIST,
|
||||
[Species.POIPOLE]: Abilities.SHEER_FORCE,
|
||||
[Species.STAKATAKA]: Abilities.SOLID_ROCK,
|
||||
[Species.BLACEPHALON]: Abilities.MAGIC_GUARD,
|
||||
[Species.ZERAORA]: Abilities.TOUGH_CLAWS,
|
||||
[Species.MELTAN]: Abilities.STEELY_SPIRIT,
|
||||
[Species.GROOKEY]: Abilities.GRASS_PELT,
|
||||
[Species.SCORBUNNY]: Abilities.NO_GUARD,
|
||||
[Species.SOBBLE]: Abilities.SUPER_LUCK,
|
||||
[Species.SKWOVET]: Abilities.HARVEST,
|
||||
[Species.ROOKIDEE]: Abilities.IRON_BARBS,
|
||||
[Species.BLIPBUG]: Abilities.PSYCHIC_SURGE,
|
||||
[Species.NICKIT]: Abilities.MAGICIAN,
|
||||
[Species.GOSSIFLEUR]: Abilities.GRASSY_SURGE,
|
||||
[Species.WOOLOO]: Abilities.SIMPLE,
|
||||
[Species.CHEWTLE]: Abilities.ROCKY_PAYLOAD,
|
||||
[Species.YAMPER]: Abilities.SHEER_FORCE,
|
||||
[Species.ROLYCOLY]: Abilities.SOLID_ROCK,
|
||||
[Species.APPLIN]: Abilities.DRAGONS_MAW,
|
||||
[Species.SILICOBRA]: Abilities.SAND_RUSH,
|
||||
[Species.CRAMORANT]: Abilities.LIGHTNING_ROD,
|
||||
[Species.ARROKUDA]: Abilities.INTIMIDATE,
|
||||
[Species.TOXEL]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.SIZZLIPEDE]: Abilities.SPEED_BOOST,
|
||||
[Species.CLOBBOPUS]: Abilities.WATER_BUBBLE,
|
||||
[Species.SINISTEA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.HATENNA]: Abilities.FAIRY_AURA,
|
||||
[Species.IMPIDIMP]: Abilities.FUR_COAT,
|
||||
[Species.MILCERY]: Abilities.REGENERATOR,
|
||||
[Species.FALINKS]: Abilities.PARENTAL_BOND,
|
||||
[Species.PINCURCHIN]: Abilities.ELECTROMORPHOSIS,
|
||||
[Species.SNOM]: Abilities.SNOW_WARNING,
|
||||
[Species.STONJOURNER]: Abilities.STURDY,
|
||||
[Species.EISCUE]: Abilities.ICE_SCALES,
|
||||
[Species.INDEEDEE]: Abilities.FRIEND_GUARD,
|
||||
[Species.MORPEKO]: Abilities.MOODY,
|
||||
[Species.CUFANT]: Abilities.EARTH_EATER,
|
||||
[Species.DRACOZOLT]: Abilities.NO_GUARD,
|
||||
[Species.ARCTOZOLT]: Abilities.TRANSISTOR,
|
||||
[Species.DRACOVISH]: Abilities.SWIFT_SWIM,
|
||||
[Species.ARCTOVISH]: Abilities.STRONG_JAW,
|
||||
[Species.DURALUDON]: Abilities.STEELWORKER,
|
||||
[Species.DREEPY]: Abilities.PARENTAL_BOND,
|
||||
[Species.ZACIAN]: Abilities.UNNERVE,
|
||||
[Species.ZAMAZENTA]: Abilities.UNNERVE,
|
||||
[Species.ETERNATUS]: Abilities.NEUTRALIZING_GAS,
|
||||
[Species.KUBFU]: Abilities.IRON_FIST,
|
||||
[Species.ZARUDE]: Abilities.TOUGH_CLAWS,
|
||||
[Species.REGIELEKI]: Abilities.ELECTRIC_SURGE,
|
||||
[Species.REGIDRAGO]: Abilities.MULTISCALE,
|
||||
[Species.GLASTRIER]: Abilities.FILTER,
|
||||
[Species.SPECTRIER]: Abilities.SHADOW_SHIELD,
|
||||
[Species.CALYREX]: Abilities.HARVEST,
|
||||
[Species.ENAMORUS]: Abilities.FAIRY_AURA,
|
||||
[Species.SPRIGATITO]: Abilities.MAGICIAN,
|
||||
[Species.FUECOCO]: Abilities.PUNK_ROCK,
|
||||
[Species.QUAXLY]: Abilities.OPPORTUNIST,
|
||||
[Species.LECHONK]: Abilities.SIMPLE,
|
||||
[Species.TAROUNTULA]: Abilities.HONEY_GATHER,
|
||||
[Species.NYMBLE]: Abilities.GUTS,
|
||||
[Species.PAWMI]: Abilities.TRANSISTOR,
|
||||
[Species.TANDEMAUS]: Abilities.SCRAPPY,
|
||||
[Species.FIDOUGH]: Abilities.WATER_ABSORB,
|
||||
[Species.SMOLIV]: Abilities.RIPEN,
|
||||
[Species.SQUAWKABILLY]: Abilities.MOXIE,
|
||||
[Species.NACLI]: Abilities.SOLID_ROCK,
|
||||
[Species.CHARCADET]: Abilities.PRISM_ARMOR,
|
||||
[Species.TADBULB]: Abilities.STAMINA,
|
||||
[Species.WATTREL]: Abilities.SHEER_FORCE,
|
||||
[Species.MASCHIFF]: Abilities.STRONG_JAW,
|
||||
[Species.SHROODLE]: Abilities.CORROSION,
|
||||
[Species.BRAMBLIN]: Abilities.SHADOW_SHIELD,
|
||||
[Species.TOEDSCOOL]: Abilities.PRANKSTER,
|
||||
[Species.KLAWF]: Abilities.WATER_ABSORB,
|
||||
[Species.CAPSAKID]: Abilities.PARENTAL_BOND,
|
||||
[Species.RELLOR]: Abilities.PRANKSTER,
|
||||
[Species.FLITTLE]: Abilities.DAZZLING,
|
||||
[Species.TINKATINK]: Abilities.STEELWORKER,
|
||||
[Species.WIGLETT]: Abilities.STURDY,
|
||||
[Species.BOMBIRDIER]: Abilities.UNBURDEN,
|
||||
[Species.FINIZEN]: Abilities.IRON_FIST,
|
||||
[Species.VAROOM]: Abilities.LEVITATE,
|
||||
[Species.CYCLIZAR]: Abilities.PROTEAN,
|
||||
[Species.ORTHWORM]: Abilities.REGENERATOR,
|
||||
[Species.GLIMMET]: Abilities.LEVITATE,
|
||||
[Species.GREAVARD]: Abilities.FUR_COAT,
|
||||
[Species.FLAMIGO]: Abilities.MOXIE,
|
||||
[Species.CETODDLE]: Abilities.ICE_SCALES,
|
||||
[Species.VELUZA]: Abilities.SUPER_LUCK,
|
||||
[Species.DONDOZO]: Abilities.PARENTAL_BOND,
|
||||
[Species.TATSUGIRI]: Abilities.ADAPTABILITY,
|
||||
[Species.GREAT_TUSK]: Abilities.INTIMIDATE,
|
||||
[Species.SCREAM_TAIL]: Abilities.UNAWARE,
|
||||
[Species.BRUTE_BONNET]: Abilities.CHLOROPHYLL,
|
||||
[Species.FLUTTER_MANE]: Abilities.DAZZLING,
|
||||
[Species.SLITHER_WING]: Abilities.SCRAPPY,
|
||||
[Species.SANDY_SHOCKS]: Abilities.EARTH_EATER,
|
||||
[Species.IRON_TREADS]: Abilities.STEELY_SPIRIT,
|
||||
[Species.IRON_BUNDLE]: Abilities.SNOW_WARNING,
|
||||
[Species.IRON_HANDS]: Abilities.IRON_FIST,
|
||||
[Species.IRON_JUGULIS]: Abilities.LIGHTNING_ROD,
|
||||
[Species.IRON_MOTH]: Abilities.LEVITATE,
|
||||
[Species.IRON_THORNS]: Abilities.SAND_STREAM,
|
||||
[Species.FRIGIBAX]: Abilities.SNOW_WARNING,
|
||||
[Species.GIMMIGHOUL]: Abilities.HONEY_GATHER,
|
||||
[Species.WO_CHIEN]: Abilities.VESSEL_OF_RUIN,
|
||||
[Species.CHIEN_PAO]: Abilities.INTIMIDATE,
|
||||
[Species.TING_LU]: Abilities.STAMINA,
|
||||
[Species.CHI_YU]: Abilities.BERSERK,
|
||||
[Species.ROARING_MOON]: Abilities.TOUGH_CLAWS,
|
||||
[Species.IRON_VALIANT]: Abilities.ADAPTABILITY,
|
||||
[Species.KORAIDON]: Abilities.OPPORTUNIST,
|
||||
[Species.MIRAIDON]: Abilities.OPPORTUNIST,
|
||||
[Species.WALKING_WAKE]: Abilities.BEAST_BOOST,
|
||||
[Species.IRON_LEAVES]: Abilities.SHARPNESS,
|
||||
[Species.POLTCHAGEIST]: Abilities.TRIAGE,
|
||||
[Species.OKIDOGI]: Abilities.FUR_COAT,
|
||||
[Species.MUNKIDORI]: Abilities.NEUROFORCE,
|
||||
[Species.FEZANDIPITI]: Abilities.LEVITATE,
|
||||
[Species.OGERPON]: Abilities.OPPORTUNIST,
|
||||
[Species.GOUGING_FIRE]: Abilities.BEAST_BOOST,
|
||||
[Species.RAGING_BOLT]: Abilities.BEAST_BOOST,
|
||||
[Species.IRON_BOULDER]: Abilities.SHARPNESS,
|
||||
[Species.IRON_CROWN]: Abilities.SHARPNESS,
|
||||
[Species.TERAPAGOS]: Abilities.SOUL_HEART,
|
||||
[Species.PECHARUNT]: Abilities.TOXIC_CHAIN,
|
||||
[Species.ALOLA_RATTATA]: Abilities.ADAPTABILITY,
|
||||
[Species.ALOLA_SANDSHREW]: Abilities.ICE_SCALES,
|
||||
[Species.ALOLA_VULPIX]: Abilities.SHEER_FORCE,
|
||||
[Species.ALOLA_DIGLETT]: Abilities.STURDY,
|
||||
[Species.ALOLA_MEOWTH]: Abilities.DARK_AURA,
|
||||
[Species.ALOLA_GEODUDE]: Abilities.DRY_SKIN,
|
||||
[Species.ALOLA_GRIMER]: Abilities.TOXIC_DEBRIS,
|
||||
[Species.ETERNAL_FLOETTE]: Abilities.MAGIC_GUARD,
|
||||
[Species.GALAR_MEOWTH]: Abilities.STEELWORKER,
|
||||
[Species.GALAR_PONYTA]: Abilities.MOXIE,
|
||||
[Species.GALAR_SLOWPOKE]: Abilities.UNAWARE,
|
||||
[Species.GALAR_FARFETCHD]: Abilities.INTREPID_SWORD,
|
||||
[Species.GALAR_ARTICUNO]: Abilities.SERENE_GRACE,
|
||||
[Species.GALAR_ZAPDOS]: Abilities.TOUGH_CLAWS,
|
||||
[Species.GALAR_MOLTRES]: Abilities.DARK_AURA,
|
||||
[Species.GALAR_CORSOLA]: Abilities.SHADOW_SHIELD,
|
||||
[Species.GALAR_ZIGZAGOON]: Abilities.POISON_HEAL,
|
||||
[Species.GALAR_DARUMAKA]: Abilities.FLASH_FIRE,
|
||||
[Species.GALAR_YAMASK]: Abilities.TABLETS_OF_RUIN,
|
||||
[Species.GALAR_STUNFISK]: Abilities.ARENA_TRAP,
|
||||
[Species.HISUI_GROWLITHE]: Abilities.RECKLESS,
|
||||
[Species.HISUI_VOLTORB]: Abilities.TRANSISTOR,
|
||||
[Species.HISUI_QWILFISH]: Abilities.MERCILESS,
|
||||
[Species.HISUI_SNEASEL]: Abilities.SCRAPPY,
|
||||
[Species.HISUI_ZORUA]: Abilities.ADAPTABILITY,
|
||||
[Species.PALDEA_TAUROS]: Abilities.ADAPTABILITY,
|
||||
[Species.PALDEA_WOOPER]: Abilities.THICK_FAT,
|
||||
[Species.BLOODMOON_URSALUNA]: Abilities.BERSERK
|
||||
};
|
@ -1,11 +1,11 @@
|
||||
import { Gender } from "./gender";
|
||||
import { PokeballType } from "./pokeball";
|
||||
import Pokemon from "../field/pokemon";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { Type } from "./type";
|
||||
import * as Utils from "../utils";
|
||||
import { WeatherType } from "./weather";
|
||||
import { Nature } from "./nature";
|
||||
import { Type } from "#app/data/type";
|
||||
import * as Utils from "#app/utils";
|
||||
import { WeatherType } from "#app/data/weather";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
53
src/data/balance/rates.ts
Normal file
53
src/data/balance/rates.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Rates for shinies and other random properties are defined in this file.
|
||||
* CHANCE is defined as x/65536
|
||||
* RATE is defined as 1/x
|
||||
*/
|
||||
|
||||
// #region Encounterable properties
|
||||
/** `64/65536 -> 1/1024` */
|
||||
export const BASE_SHINY_CHANCE = 64;
|
||||
|
||||
/** `256/65536 -> 1/256` */
|
||||
export const BASE_HIDDEN_ABILITY_CHANCE = 256;
|
||||
|
||||
// #region Egg properties
|
||||
|
||||
// Threshold x at which a gacha egg is determined to be a certain tier
|
||||
// Specifically, the tier is determined by the highest threshold a random value between 0-255 meets or exceeds
|
||||
// Legendary Up Gacha raises these thresholds by 1, thereby giving Legendary eggs 2/256 chance
|
||||
export const GACHA_DEFAULT_COMMON_EGG_THRESHOLD = 52; // Default 204/256 chance, 203/256 chance in Legendary Up Gacha
|
||||
export const GACHA_DEFAULT_RARE_EGG_THRESHOLD = 8; // Default 44/256 chance
|
||||
export const GACHA_DEFAULT_EPIC_EGG_THRESHOLD = 1; // Default 7/256 chance, leaving Legendary as 1/256 chance
|
||||
export const GACHA_LEGENDARY_UP_THRESHOLD_OFFSET = 1; // The offset to threshold for Legendary Up gacha eggs. +x/256 Legendary Egg chance, -x/256 Common Egg chance
|
||||
|
||||
// The number of eggs without finding a certain tier egg it takes for egg pity to kick in and that tier to be forced
|
||||
// These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered.
|
||||
export const EGG_PITY_LEGENDARY_THRESHOLD = 412;
|
||||
export const EGG_PITY_EPIC_THRESHOLD = 59;
|
||||
export const EGG_PITY_RARE_THRESHOLD = 9;
|
||||
|
||||
// Waves to hatch an egg of a given tier
|
||||
export const HATCH_WAVES_COMMON_EGG = 10;
|
||||
export const HATCH_WAVES_RARE_EGG = 25;
|
||||
export const HATCH_WAVES_EPIC_EGG = 50;
|
||||
export const HATCH_WAVES_LEGENDARY_EGG = 100;
|
||||
export const HATCH_WAVES_MANAPHY_EGG = 50;
|
||||
|
||||
// Rates for specific random properties in 1/x
|
||||
export const GACHA_DEFAULT_SHINY_RATE = 128;
|
||||
export const GACHA_SHINY_UP_SHINY_RATE = 64;
|
||||
export const SAME_SPECIES_EGG_SHINY_RATE = 12;
|
||||
export const SAME_SPECIES_EGG_HA_RATE = 8;
|
||||
export const MANAPHY_EGG_MANAPHY_RATE = 8;
|
||||
export const GACHA_EGG_HA_RATE = 192;
|
||||
|
||||
// 1/x for legendary eggs, 1/x*2 for epic eggs, 1/x*4 for rare eggs, and 1/x*8 for common eggs
|
||||
export const GACHA_DEFAULT_RARE_EGGMOVE_RATE = 6;
|
||||
export const SAME_SPECIES_EGG_RARE_EGGMOVE_RATE = 3;
|
||||
export const GACHA_MOVE_UP_RARE_EGGMOVE_RATE = 3;
|
||||
|
||||
// #region Variant properties
|
||||
// The chance x/10 of a shiny being a variant, then of being specifically an epic variant
|
||||
export const SHINY_VARIANT_CHANCE = 4;
|
||||
export const SHINY_EPIC_CHANCE = 1;
|
671
src/data/balance/starters.ts
Normal file
671
src/data/balance/starters.ts
Normal file
@ -0,0 +1,671 @@
|
||||
import { Species } from "#enums/species";
|
||||
|
||||
export const POKERUS_STARTER_COUNT = 5;
|
||||
|
||||
/**
|
||||
* Function to get the cumulative friendship threshold at which a candy is earned
|
||||
* @param starterCost The cost of the starter, found in {@linkcode speciesStarterCosts}
|
||||
* @returns aforementioned threshold
|
||||
*/
|
||||
export function getStarterValueFriendshipCap(starterCost: number): number {
|
||||
switch (starterCost) {
|
||||
case 1:
|
||||
return 20;
|
||||
case 2:
|
||||
return 40;
|
||||
case 3:
|
||||
return 60;
|
||||
case 4:
|
||||
return 100;
|
||||
case 5:
|
||||
return 140;
|
||||
case 6:
|
||||
return 200;
|
||||
case 7:
|
||||
return 280;
|
||||
case 8:
|
||||
case 9:
|
||||
return 450;
|
||||
default:
|
||||
return 600;
|
||||
}
|
||||
}
|
||||
|
||||
export const speciesStarterCosts = {
|
||||
[Species.BULBASAUR]: 3,
|
||||
[Species.CHARMANDER]: 3,
|
||||
[Species.SQUIRTLE]: 3,
|
||||
[Species.CATERPIE]: 2,
|
||||
[Species.WEEDLE]: 1,
|
||||
[Species.PIDGEY]: 1,
|
||||
[Species.RATTATA]: 1,
|
||||
[Species.SPEAROW]: 1,
|
||||
[Species.EKANS]: 2,
|
||||
[Species.PIKACHU]: 3,
|
||||
[Species.SANDSHREW]: 2,
|
||||
[Species.NIDORAN_F]: 3,
|
||||
[Species.NIDORAN_M]: 3,
|
||||
[Species.CLEFAIRY]: 3,
|
||||
[Species.VULPIX]: 3,
|
||||
[Species.JIGGLYPUFF]: 2,
|
||||
[Species.ZUBAT]: 3,
|
||||
[Species.ODDISH]: 3,
|
||||
[Species.PARAS]: 2,
|
||||
[Species.VENONAT]: 2,
|
||||
[Species.DIGLETT]: 2,
|
||||
[Species.MEOWTH]: 3,
|
||||
[Species.PSYDUCK]: 2,
|
||||
[Species.MANKEY]: 4,
|
||||
[Species.GROWLITHE]: 4,
|
||||
[Species.POLIWAG]: 2,
|
||||
[Species.ABRA]: 4,
|
||||
[Species.MACHOP]: 3,
|
||||
[Species.BELLSPROUT]: 2,
|
||||
[Species.TENTACOOL]: 3,
|
||||
[Species.GEODUDE]: 3,
|
||||
[Species.PONYTA]: 2,
|
||||
[Species.SLOWPOKE]: 3,
|
||||
[Species.MAGNEMITE]: 4,
|
||||
[Species.FARFETCHD]: 2,
|
||||
[Species.DODUO]: 3,
|
||||
[Species.SEEL]: 1,
|
||||
[Species.GRIMER]: 2,
|
||||
[Species.SHELLDER]: 5,
|
||||
[Species.GASTLY]: 4,
|
||||
[Species.ONIX]: 3,
|
||||
[Species.DROWZEE]: 2,
|
||||
[Species.KRABBY]: 3,
|
||||
[Species.VOLTORB]: 2,
|
||||
[Species.EXEGGCUTE]: 3,
|
||||
[Species.CUBONE]: 3,
|
||||
[Species.HITMONLEE]: 4,
|
||||
[Species.HITMONCHAN]: 4,
|
||||
[Species.LICKITUNG]: 3,
|
||||
[Species.KOFFING]: 2,
|
||||
[Species.RHYHORN]: 3,
|
||||
[Species.CHANSEY]: 3,
|
||||
[Species.TANGELA]: 3,
|
||||
[Species.KANGASKHAN]: 4,
|
||||
[Species.HORSEA]: 3,
|
||||
[Species.GOLDEEN]: 2,
|
||||
[Species.STARYU]: 3,
|
||||
[Species.MR_MIME]: 3,
|
||||
[Species.SCYTHER]: 5,
|
||||
[Species.JYNX]: 4,
|
||||
[Species.ELECTABUZZ]: 4,
|
||||
[Species.MAGMAR]: 4,
|
||||
[Species.PINSIR]: 4,
|
||||
[Species.TAUROS]: 4,
|
||||
[Species.MAGIKARP]: 4,
|
||||
[Species.LAPRAS]: 4,
|
||||
[Species.DITTO]: 2,
|
||||
[Species.EEVEE]: 3,
|
||||
[Species.PORYGON]: 4,
|
||||
[Species.OMANYTE]: 3,
|
||||
[Species.KABUTO]: 3,
|
||||
[Species.AERODACTYL]: 5,
|
||||
[Species.SNORLAX]: 5,
|
||||
[Species.ARTICUNO]: 6,
|
||||
[Species.ZAPDOS]: 6,
|
||||
[Species.MOLTRES]: 6,
|
||||
[Species.DRATINI]: 4,
|
||||
[Species.MEWTWO]: 8,
|
||||
[Species.MEW]: 6,
|
||||
|
||||
[Species.CHIKORITA]: 2,
|
||||
[Species.CYNDAQUIL]: 3,
|
||||
[Species.TOTODILE]: 3,
|
||||
[Species.SENTRET]: 1,
|
||||
[Species.HOOTHOOT]: 2,
|
||||
[Species.LEDYBA]: 1,
|
||||
[Species.SPINARAK]: 1,
|
||||
[Species.CHINCHOU]: 2,
|
||||
[Species.PICHU]: 2,
|
||||
[Species.CLEFFA]: 2,
|
||||
[Species.IGGLYBUFF]: 1,
|
||||
[Species.TOGEPI]: 3,
|
||||
[Species.NATU]: 2,
|
||||
[Species.MAREEP]: 2,
|
||||
[Species.MARILL]: 4,
|
||||
[Species.SUDOWOODO]: 3,
|
||||
[Species.HOPPIP]: 2,
|
||||
[Species.AIPOM]: 2,
|
||||
[Species.SUNKERN]: 1,
|
||||
[Species.YANMA]: 3,
|
||||
[Species.WOOPER]: 2,
|
||||
[Species.MURKROW]: 3,
|
||||
[Species.MISDREAVUS]: 2,
|
||||
[Species.UNOWN]: 1,
|
||||
[Species.WOBBUFFET]: 2,
|
||||
[Species.GIRAFARIG]: 3,
|
||||
[Species.PINECO]: 2,
|
||||
[Species.DUNSPARCE]: 3,
|
||||
[Species.GLIGAR]: 3,
|
||||
[Species.SNUBBULL]: 2,
|
||||
[Species.QWILFISH]: 3,
|
||||
[Species.SHUCKLE]: 3,
|
||||
[Species.HERACROSS]: 5,
|
||||
[Species.SNEASEL]: 4,
|
||||
[Species.TEDDIURSA]: 4,
|
||||
[Species.SLUGMA]: 2,
|
||||
[Species.SWINUB]: 3,
|
||||
[Species.CORSOLA]: 2,
|
||||
[Species.REMORAID]: 2,
|
||||
[Species.DELIBIRD]: 2,
|
||||
[Species.MANTINE]: 3,
|
||||
[Species.SKARMORY]: 4,
|
||||
[Species.HOUNDOUR]: 3,
|
||||
[Species.PHANPY]: 3,
|
||||
[Species.STANTLER]: 3,
|
||||
[Species.SMEARGLE]: 1,
|
||||
[Species.TYROGUE]: 3,
|
||||
[Species.SMOOCHUM]: 3,
|
||||
[Species.ELEKID]: 3,
|
||||
[Species.MAGBY]: 3,
|
||||
[Species.MILTANK]: 4,
|
||||
[Species.RAIKOU]: 6,
|
||||
[Species.ENTEI]: 6,
|
||||
[Species.SUICUNE]: 6,
|
||||
[Species.LARVITAR]: 4,
|
||||
[Species.LUGIA]: 8,
|
||||
[Species.HO_OH]: 8,
|
||||
[Species.CELEBI]: 6,
|
||||
|
||||
[Species.TREECKO]: 3,
|
||||
[Species.TORCHIC]: 4,
|
||||
[Species.MUDKIP]: 3,
|
||||
[Species.POOCHYENA]: 2,
|
||||
[Species.ZIGZAGOON]: 2,
|
||||
[Species.WURMPLE]: 1,
|
||||
[Species.LOTAD]: 3,
|
||||
[Species.SEEDOT]: 2,
|
||||
[Species.TAILLOW]: 3,
|
||||
[Species.WINGULL]: 2,
|
||||
[Species.RALTS]: 3,
|
||||
[Species.SURSKIT]: 2,
|
||||
[Species.SHROOMISH]: 3,
|
||||
[Species.SLAKOTH]: 4,
|
||||
[Species.NINCADA]: 4,
|
||||
[Species.WHISMUR]: 2,
|
||||
[Species.MAKUHITA]: 3,
|
||||
[Species.AZURILL]: 4,
|
||||
[Species.NOSEPASS]: 2,
|
||||
[Species.SKITTY]: 1,
|
||||
[Species.SABLEYE]: 2,
|
||||
[Species.MAWILE]: 3,
|
||||
[Species.ARON]: 3,
|
||||
[Species.MEDITITE]: 3,
|
||||
[Species.ELECTRIKE]: 2,
|
||||
[Species.PLUSLE]: 2,
|
||||
[Species.MINUN]: 2,
|
||||
[Species.VOLBEAT]: 2,
|
||||
[Species.ILLUMISE]: 2,
|
||||
[Species.ROSELIA]: 3,
|
||||
[Species.GULPIN]: 1,
|
||||
[Species.CARVANHA]: 3,
|
||||
[Species.WAILMER]: 2,
|
||||
[Species.NUMEL]: 2,
|
||||
[Species.TORKOAL]: 3,
|
||||
[Species.SPOINK]: 2,
|
||||
[Species.SPINDA]: 1,
|
||||
[Species.TRAPINCH]: 3,
|
||||
[Species.CACNEA]: 2,
|
||||
[Species.SWABLU]: 2,
|
||||
[Species.ZANGOOSE]: 4,
|
||||
[Species.SEVIPER]: 3,
|
||||
[Species.LUNATONE]: 3,
|
||||
[Species.SOLROCK]: 3,
|
||||
[Species.BARBOACH]: 2,
|
||||
[Species.CORPHISH]: 3,
|
||||
[Species.BALTOY]: 2,
|
||||
[Species.LILEEP]: 3,
|
||||
[Species.ANORITH]: 3,
|
||||
[Species.FEEBAS]: 4,
|
||||
[Species.CASTFORM]: 1,
|
||||
[Species.KECLEON]: 2,
|
||||
[Species.SHUPPET]: 2,
|
||||
[Species.DUSKULL]: 3,
|
||||
[Species.TROPIUS]: 3,
|
||||
[Species.CHIMECHO]: 3,
|
||||
[Species.ABSOL]: 4,
|
||||
[Species.WYNAUT]: 2,
|
||||
[Species.SNORUNT]: 2,
|
||||
[Species.SPHEAL]: 2,
|
||||
[Species.CLAMPERL]: 3,
|
||||
[Species.RELICANTH]: 3,
|
||||
[Species.LUVDISC]: 1,
|
||||
[Species.BAGON]: 4,
|
||||
[Species.BELDUM]: 4,
|
||||
[Species.REGIROCK]: 6,
|
||||
[Species.REGICE]: 6,
|
||||
[Species.REGISTEEL]: 6,
|
||||
[Species.LATIAS]: 7,
|
||||
[Species.LATIOS]: 7,
|
||||
[Species.KYOGRE]: 9,
|
||||
[Species.GROUDON]: 9,
|
||||
[Species.RAYQUAZA]: 9,
|
||||
[Species.JIRACHI]: 7,
|
||||
[Species.DEOXYS]: 7,
|
||||
|
||||
[Species.TURTWIG]: 3,
|
||||
[Species.CHIMCHAR]: 3,
|
||||
[Species.PIPLUP]: 3,
|
||||
[Species.STARLY]: 3,
|
||||
[Species.BIDOOF]: 2,
|
||||
[Species.KRICKETOT]: 1,
|
||||
[Species.SHINX]: 2,
|
||||
[Species.BUDEW]: 3,
|
||||
[Species.CRANIDOS]: 3,
|
||||
[Species.SHIELDON]: 3,
|
||||
[Species.BURMY]: 2,
|
||||
[Species.COMBEE]: 2,
|
||||
[Species.PACHIRISU]: 2,
|
||||
[Species.BUIZEL]: 2,
|
||||
[Species.CHERUBI]: 1,
|
||||
[Species.SHELLOS]: 3,
|
||||
[Species.DRIFLOON]: 2,
|
||||
[Species.BUNEARY]: 2,
|
||||
[Species.GLAMEOW]: 2,
|
||||
[Species.CHINGLING]: 2,
|
||||
[Species.STUNKY]: 2,
|
||||
[Species.BRONZOR]: 3,
|
||||
[Species.BONSLY]: 2,
|
||||
[Species.MIME_JR]: 2,
|
||||
[Species.HAPPINY]: 2,
|
||||
[Species.CHATOT]: 2,
|
||||
[Species.SPIRITOMB]: 4,
|
||||
[Species.GIBLE]: 4,
|
||||
[Species.MUNCHLAX]: 4,
|
||||
[Species.RIOLU]: 3,
|
||||
[Species.HIPPOPOTAS]: 3,
|
||||
[Species.SKORUPI]: 3,
|
||||
[Species.CROAGUNK]: 2,
|
||||
[Species.CARNIVINE]: 2,
|
||||
[Species.FINNEON]: 1,
|
||||
[Species.MANTYKE]: 2,
|
||||
[Species.SNOVER]: 2,
|
||||
[Species.ROTOM]: 5,
|
||||
[Species.UXIE]: 6,
|
||||
[Species.MESPRIT]: 6,
|
||||
[Species.AZELF]: 6,
|
||||
[Species.DIALGA]: 8,
|
||||
[Species.PALKIA]: 8,
|
||||
[Species.HEATRAN]: 6,
|
||||
[Species.REGIGIGAS]: 7,
|
||||
[Species.GIRATINA]: 8,
|
||||
[Species.CRESSELIA]: 6,
|
||||
[Species.PHIONE]: 4,
|
||||
[Species.MANAPHY]: 7,
|
||||
[Species.DARKRAI]: 7,
|
||||
[Species.SHAYMIN]: 6,
|
||||
[Species.ARCEUS]: 9,
|
||||
|
||||
[Species.VICTINI]: 7,
|
||||
[Species.SNIVY]: 3,
|
||||
[Species.TEPIG]: 3,
|
||||
[Species.OSHAWOTT]: 3,
|
||||
[Species.PATRAT]: 1,
|
||||
[Species.LILLIPUP]: 3,
|
||||
[Species.PURRLOIN]: 2,
|
||||
[Species.PANSAGE]: 2,
|
||||
[Species.PANSEAR]: 2,
|
||||
[Species.PANPOUR]: 2,
|
||||
[Species.MUNNA]: 2,
|
||||
[Species.PIDOVE]: 1,
|
||||
[Species.BLITZLE]: 2,
|
||||
[Species.ROGGENROLA]: 3,
|
||||
[Species.WOOBAT]: 3,
|
||||
[Species.DRILBUR]: 4,
|
||||
[Species.AUDINO]: 3,
|
||||
[Species.TIMBURR]: 4,
|
||||
[Species.TYMPOLE]: 3,
|
||||
[Species.THROH]: 4,
|
||||
[Species.SAWK]: 4,
|
||||
[Species.SEWADDLE]: 2,
|
||||
[Species.VENIPEDE]: 3,
|
||||
[Species.COTTONEE]: 3,
|
||||
[Species.PETILIL]: 3,
|
||||
[Species.BASCULIN]: 4,
|
||||
[Species.SANDILE]: 4,
|
||||
[Species.DARUMAKA]: 4,
|
||||
[Species.MARACTUS]: 2,
|
||||
[Species.DWEBBLE]: 2,
|
||||
[Species.SCRAGGY]: 3,
|
||||
[Species.SIGILYPH]: 4,
|
||||
[Species.YAMASK]: 3,
|
||||
[Species.TIRTOUGA]: 3,
|
||||
[Species.ARCHEN]: 3,
|
||||
[Species.TRUBBISH]: 2,
|
||||
[Species.ZORUA]: 3,
|
||||
[Species.MINCCINO]: 3,
|
||||
[Species.GOTHITA]: 3,
|
||||
[Species.SOLOSIS]: 3,
|
||||
[Species.DUCKLETT]: 2,
|
||||
[Species.VANILLITE]: 3,
|
||||
[Species.DEERLING]: 2,
|
||||
[Species.EMOLGA]: 2,
|
||||
[Species.KARRABLAST]: 3,
|
||||
[Species.FOONGUS]: 2,
|
||||
[Species.FRILLISH]: 3,
|
||||
[Species.ALOMOMOLA]: 4,
|
||||
[Species.JOLTIK]: 3,
|
||||
[Species.FERROSEED]: 3,
|
||||
[Species.KLINK]: 3,
|
||||
[Species.TYNAMO]: 2,
|
||||
[Species.ELGYEM]: 2,
|
||||
[Species.LITWICK]: 3,
|
||||
[Species.AXEW]: 4,
|
||||
[Species.CUBCHOO]: 2,
|
||||
[Species.CRYOGONAL]: 4,
|
||||
[Species.SHELMET]: 2,
|
||||
[Species.STUNFISK]: 3,
|
||||
[Species.MIENFOO]: 3,
|
||||
[Species.DRUDDIGON]: 4,
|
||||
[Species.GOLETT]: 3,
|
||||
[Species.PAWNIARD]: 4,
|
||||
[Species.BOUFFALANT]: 4,
|
||||
[Species.RUFFLET]: 3,
|
||||
[Species.VULLABY]: 3,
|
||||
[Species.HEATMOR]: 3,
|
||||
[Species.DURANT]: 4,
|
||||
[Species.DEINO]: 4,
|
||||
[Species.LARVESTA]: 4,
|
||||
[Species.COBALION]: 6,
|
||||
[Species.TERRAKION]: 6,
|
||||
[Species.VIRIZION]: 6,
|
||||
[Species.TORNADUS]: 7,
|
||||
[Species.THUNDURUS]: 7,
|
||||
[Species.RESHIRAM]: 8,
|
||||
[Species.ZEKROM]: 8,
|
||||
[Species.LANDORUS]: 7,
|
||||
[Species.KYUREM]: 8,
|
||||
[Species.KELDEO]: 6,
|
||||
[Species.MELOETTA]: 7,
|
||||
[Species.GENESECT]: 6,
|
||||
|
||||
[Species.CHESPIN]: 3,
|
||||
[Species.FENNEKIN]: 3,
|
||||
[Species.FROAKIE]: 4,
|
||||
[Species.BUNNELBY]: 3,
|
||||
[Species.FLETCHLING]: 3,
|
||||
[Species.SCATTERBUG]: 2,
|
||||
[Species.LITLEO]: 2,
|
||||
[Species.FLABEBE]: 3,
|
||||
[Species.SKIDDO]: 2,
|
||||
[Species.PANCHAM]: 3,
|
||||
[Species.FURFROU]: 3,
|
||||
[Species.ESPURR]: 2,
|
||||
[Species.HONEDGE]: 4,
|
||||
[Species.SPRITZEE]: 2,
|
||||
[Species.SWIRLIX]: 3,
|
||||
[Species.INKAY]: 3,
|
||||
[Species.BINACLE]: 3,
|
||||
[Species.SKRELP]: 2,
|
||||
[Species.CLAUNCHER]: 3,
|
||||
[Species.HELIOPTILE]: 3,
|
||||
[Species.TYRUNT]: 3,
|
||||
[Species.AMAURA]: 3,
|
||||
[Species.HAWLUCHA]: 4,
|
||||
[Species.DEDENNE]: 2,
|
||||
[Species.CARBINK]: 2,
|
||||
[Species.GOOMY]: 4,
|
||||
[Species.KLEFKI]: 3,
|
||||
[Species.PHANTUMP]: 2,
|
||||
[Species.PUMPKABOO]: 2,
|
||||
[Species.BERGMITE]: 3,
|
||||
[Species.NOIBAT]: 3,
|
||||
[Species.XERNEAS]: 8,
|
||||
[Species.YVELTAL]: 8,
|
||||
[Species.ZYGARDE]: 8,
|
||||
[Species.DIANCIE]: 7,
|
||||
[Species.HOOPA]: 7,
|
||||
[Species.VOLCANION]: 6,
|
||||
[Species.ETERNAL_FLOETTE]: 4,
|
||||
|
||||
[Species.ROWLET]: 3,
|
||||
[Species.LITTEN]: 3,
|
||||
[Species.POPPLIO]: 4,
|
||||
[Species.PIKIPEK]: 2,
|
||||
[Species.YUNGOOS]: 2,
|
||||
[Species.GRUBBIN]: 3,
|
||||
[Species.CRABRAWLER]: 3,
|
||||
[Species.ORICORIO]: 3,
|
||||
[Species.CUTIEFLY]: 3,
|
||||
[Species.ROCKRUFF]: 3,
|
||||
[Species.WISHIWASHI]: 2,
|
||||
[Species.MAREANIE]: 2,
|
||||
[Species.MUDBRAY]: 3,
|
||||
[Species.DEWPIDER]: 3,
|
||||
[Species.FOMANTIS]: 2,
|
||||
[Species.MORELULL]: 2,
|
||||
[Species.SALANDIT]: 3,
|
||||
[Species.STUFFUL]: 3,
|
||||
[Species.BOUNSWEET]: 3,
|
||||
[Species.COMFEY]: 4,
|
||||
[Species.ORANGURU]: 4,
|
||||
[Species.PASSIMIAN]: 4,
|
||||
[Species.WIMPOD]: 3,
|
||||
[Species.SANDYGAST]: 3,
|
||||
[Species.PYUKUMUKU]: 2,
|
||||
[Species.TYPE_NULL]: 5,
|
||||
[Species.MINIOR]: 4,
|
||||
[Species.KOMALA]: 3,
|
||||
[Species.TURTONATOR]: 4,
|
||||
[Species.TOGEDEMARU]: 3,
|
||||
[Species.MIMIKYU]: 4,
|
||||
[Species.BRUXISH]: 4,
|
||||
[Species.DRAMPA]: 4,
|
||||
[Species.DHELMISE]: 4,
|
||||
[Species.JANGMO_O]: 4,
|
||||
[Species.TAPU_KOKO]: 6,
|
||||
[Species.TAPU_LELE]: 6,
|
||||
[Species.TAPU_BULU]: 6,
|
||||
[Species.TAPU_FINI]: 6,
|
||||
[Species.COSMOG]: 7,
|
||||
[Species.NIHILEGO]: 6,
|
||||
[Species.BUZZWOLE]: 6,
|
||||
[Species.PHEROMOSA]: 7,
|
||||
[Species.XURKITREE]: 6,
|
||||
[Species.CELESTEELA]: 6,
|
||||
[Species.KARTANA]: 7,
|
||||
[Species.GUZZLORD]: 6,
|
||||
[Species.NECROZMA]: 8,
|
||||
[Species.MAGEARNA]: 7,
|
||||
[Species.MARSHADOW]: 7,
|
||||
[Species.POIPOLE]: 7,
|
||||
[Species.STAKATAKA]: 6,
|
||||
[Species.BLACEPHALON]: 7,
|
||||
[Species.ZERAORA]: 6,
|
||||
[Species.MELTAN]: 6,
|
||||
[Species.ALOLA_RATTATA]: 1,
|
||||
[Species.ALOLA_SANDSHREW]: 2,
|
||||
[Species.ALOLA_VULPIX]: 3,
|
||||
[Species.ALOLA_DIGLETT]: 2,
|
||||
[Species.ALOLA_MEOWTH]: 3,
|
||||
[Species.ALOLA_GEODUDE]: 3,
|
||||
[Species.ALOLA_GRIMER]: 3,
|
||||
|
||||
[Species.GROOKEY]: 3,
|
||||
[Species.SCORBUNNY]: 4,
|
||||
[Species.SOBBLE]: 3,
|
||||
[Species.SKWOVET]: 2,
|
||||
[Species.ROOKIDEE]: 3,
|
||||
[Species.BLIPBUG]: 2,
|
||||
[Species.NICKIT]: 1,
|
||||
[Species.GOSSIFLEUR]: 2,
|
||||
[Species.WOOLOO]: 2,
|
||||
[Species.CHEWTLE]: 3,
|
||||
[Species.YAMPER]: 2,
|
||||
[Species.ROLYCOLY]: 3,
|
||||
[Species.APPLIN]: 3,
|
||||
[Species.SILICOBRA]: 3,
|
||||
[Species.CRAMORANT]: 3,
|
||||
[Species.ARROKUDA]: 3,
|
||||
[Species.TOXEL]: 3,
|
||||
[Species.SIZZLIPEDE]: 3,
|
||||
[Species.CLOBBOPUS]: 2,
|
||||
[Species.SINISTEA]: 3,
|
||||
[Species.HATENNA]: 3,
|
||||
[Species.IMPIDIMP]: 3,
|
||||
[Species.MILCERY]: 3,
|
||||
[Species.FALINKS]: 4,
|
||||
[Species.PINCURCHIN]: 3,
|
||||
[Species.SNOM]: 3,
|
||||
[Species.STONJOURNER]: 3,
|
||||
[Species.EISCUE]: 3,
|
||||
[Species.INDEEDEE]: 4,
|
||||
[Species.MORPEKO]: 3,
|
||||
[Species.CUFANT]: 3,
|
||||
[Species.DRACOZOLT]: 5,
|
||||
[Species.ARCTOZOLT]: 4,
|
||||
[Species.DRACOVISH]: 5,
|
||||
[Species.ARCTOVISH]: 4,
|
||||
[Species.DURALUDON]: 5,
|
||||
[Species.DREEPY]: 4,
|
||||
[Species.ZACIAN]: 9,
|
||||
[Species.ZAMAZENTA]: 8,
|
||||
[Species.ETERNATUS]: 10,
|
||||
[Species.KUBFU]: 6,
|
||||
[Species.ZARUDE]: 6,
|
||||
[Species.REGIELEKI]: 6,
|
||||
[Species.REGIDRAGO]: 6,
|
||||
[Species.GLASTRIER]: 6,
|
||||
[Species.SPECTRIER]: 7,
|
||||
[Species.CALYREX]: 8,
|
||||
[Species.GALAR_MEOWTH]: 3,
|
||||
[Species.GALAR_PONYTA]: 2,
|
||||
[Species.GALAR_SLOWPOKE]: 3,
|
||||
[Species.GALAR_FARFETCHD]: 3,
|
||||
[Species.GALAR_CORSOLA]: 3,
|
||||
[Species.GALAR_ZIGZAGOON]: 3,
|
||||
[Species.GALAR_DARUMAKA]: 4,
|
||||
[Species.GALAR_YAMASK]: 3,
|
||||
[Species.GALAR_STUNFISK]: 2,
|
||||
[Species.GALAR_MR_MIME]: 3,
|
||||
[Species.GALAR_ARTICUNO]: 6,
|
||||
[Species.GALAR_ZAPDOS]: 6,
|
||||
[Species.GALAR_MOLTRES]: 6,
|
||||
[Species.HISUI_GROWLITHE]: 4,
|
||||
[Species.HISUI_VOLTORB]: 3,
|
||||
[Species.HISUI_QWILFISH]: 4,
|
||||
[Species.HISUI_SNEASEL]: 5,
|
||||
[Species.HISUI_ZORUA]: 3,
|
||||
[Species.ENAMORUS]: 7,
|
||||
|
||||
[Species.SPRIGATITO]: 4,
|
||||
[Species.FUECOCO]: 4,
|
||||
[Species.QUAXLY]: 4,
|
||||
[Species.LECHONK]: 2,
|
||||
[Species.TAROUNTULA]: 1,
|
||||
[Species.NYMBLE]: 3,
|
||||
[Species.PAWMI]: 3,
|
||||
[Species.TANDEMAUS]: 4,
|
||||
[Species.FIDOUGH]: 2,
|
||||
[Species.SMOLIV]: 3,
|
||||
[Species.SQUAWKABILLY]: 2,
|
||||
[Species.NACLI]: 4,
|
||||
[Species.CHARCADET]: 4,
|
||||
[Species.TADBULB]: 3,
|
||||
[Species.WATTREL]: 3,
|
||||
[Species.MASCHIFF]: 3,
|
||||
[Species.SHROODLE]: 2,
|
||||
[Species.BRAMBLIN]: 3,
|
||||
[Species.TOEDSCOOL]: 3,
|
||||
[Species.KLAWF]: 3,
|
||||
[Species.CAPSAKID]: 3,
|
||||
[Species.RELLOR]: 2,
|
||||
[Species.FLITTLE]: 3,
|
||||
[Species.TINKATINK]: 4,
|
||||
[Species.WIGLETT]: 2,
|
||||
[Species.BOMBIRDIER]: 3,
|
||||
[Species.FINIZEN]: 3,
|
||||
[Species.VAROOM]: 4,
|
||||
[Species.CYCLIZAR]: 4,
|
||||
[Species.ORTHWORM]: 4,
|
||||
[Species.GLIMMET]: 4,
|
||||
[Species.GREAVARD]: 3,
|
||||
[Species.FLAMIGO]: 4,
|
||||
[Species.CETODDLE]: 3,
|
||||
[Species.VELUZA]: 4,
|
||||
[Species.DONDOZO]: 4,
|
||||
[Species.TATSUGIRI]: 4,
|
||||
[Species.GREAT_TUSK]: 6,
|
||||
[Species.SCREAM_TAIL]: 6,
|
||||
[Species.BRUTE_BONNET]: 6,
|
||||
[Species.FLUTTER_MANE]: 7,
|
||||
[Species.SLITHER_WING]: 6,
|
||||
[Species.SANDY_SHOCKS]: 6,
|
||||
[Species.IRON_TREADS]: 6,
|
||||
[Species.IRON_BUNDLE]: 6,
|
||||
[Species.IRON_HANDS]: 6,
|
||||
[Species.IRON_JUGULIS]: 6,
|
||||
[Species.IRON_MOTH]: 6,
|
||||
[Species.IRON_THORNS]: 6,
|
||||
[Species.FRIGIBAX]: 4,
|
||||
[Species.GIMMIGHOUL]: 4,
|
||||
[Species.WO_CHIEN]: 6,
|
||||
[Species.CHIEN_PAO]: 7,
|
||||
[Species.TING_LU]: 6,
|
||||
[Species.CHI_YU]: 7,
|
||||
[Species.ROARING_MOON]: 6,
|
||||
[Species.IRON_VALIANT]: 6,
|
||||
[Species.KORAIDON]: 9,
|
||||
[Species.MIRAIDON]: 9,
|
||||
[Species.WALKING_WAKE]: 6,
|
||||
[Species.IRON_LEAVES]: 6,
|
||||
[Species.POLTCHAGEIST]: 4,
|
||||
[Species.OKIDOGI]: 6,
|
||||
[Species.MUNKIDORI]: 6,
|
||||
[Species.FEZANDIPITI]: 6,
|
||||
[Species.OGERPON]: 7,
|
||||
[Species.GOUGING_FIRE]: 7,
|
||||
[Species.RAGING_BOLT]: 6,
|
||||
[Species.IRON_BOULDER]: 7,
|
||||
[Species.IRON_CROWN]: 6,
|
||||
[Species.TERAPAGOS]: 8,
|
||||
[Species.PECHARUNT]: 6,
|
||||
[Species.PALDEA_TAUROS]: 5,
|
||||
[Species.PALDEA_WOOPER]: 3,
|
||||
[Species.BLOODMOON_URSALUNA]: 6,
|
||||
};
|
||||
|
||||
const starterCandyCosts: { passive: number; costReduction: [number, number]; egg: number; }[] = [
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 1 Cost
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 2 Cost
|
||||
{ passive: 35, costReduction: [20, 50], egg: 25 }, // 3 Cost
|
||||
{ passive: 30, costReduction: [15, 40], egg: 20 }, // 4 Cost
|
||||
{ passive: 25, costReduction: [12, 35], egg: 18 }, // 5 Cost
|
||||
{ passive: 20, costReduction: [10, 30], egg: 15 }, // 6 Cost
|
||||
{ passive: 15, costReduction: [8, 20], egg: 12 }, // 7 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 8 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 9 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 10 Cost
|
||||
];
|
||||
|
||||
/**
|
||||
* Getter for {@linkcode starterCandyCosts} for passive unlock candy cost based on initial point cost
|
||||
* @param starterCost the default point cost of the starter found in {@linkcode speciesStarterCosts}
|
||||
* @returns the candy cost for passive unlock
|
||||
*/
|
||||
export function getPassiveCandyCount(starterCost: number): number {
|
||||
return starterCandyCosts[starterCost - 1].passive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for {@linkcode starterCandyCosts} for value reduction unlock candy cost based on initial point cost
|
||||
* @param starterCost the default point cost of the starter found in {@linkcode speciesStarterCosts}
|
||||
* @returns respective candy cost for the two cost reductions as an array 2 numbers
|
||||
*/
|
||||
export function getValueReductionCandyCounts(starterCost: number): [number, number] {
|
||||
return starterCandyCosts[starterCost - 1].costReduction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for {@linkcode starterCandyCosts} for egg purchase candy cost based on initial point cost
|
||||
* @param starterCost the default point cost of the starter found in {@linkcode speciesStarterCosts}
|
||||
* @returns the candy cost for the purchasable egg
|
||||
*/
|
||||
export function getSameSpeciesEggCandyCounts(starterCost: number): number {
|
||||
return starterCandyCosts[starterCost - 1].egg;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ModifierTier } from "../modifier/modifier-tier";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
|
@ -2267,7 +2267,7 @@ export class HealBlockTag extends MoveRestrictionBattlerTag {
|
||||
* Uses DisabledTag's selectionDeniedText() message
|
||||
*/
|
||||
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveDisabled", { moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledHealBlock", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name, healBlockName: allMoves[Moves.HEAL_BLOCK].name });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2277,7 +2277,7 @@ export class HealBlockTag extends MoveRestrictionBattlerTag {
|
||||
* @returns {string} text to display when the move is interrupted
|
||||
*/
|
||||
override interruptedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledHealBlock", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name, healBlockName: allMoves[Moves.HEAL_BLOCK].name });
|
||||
}
|
||||
|
||||
override onRemove(pokemon: Pokemon): void {
|
||||
@ -2530,8 +2530,8 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
return false;
|
||||
}
|
||||
|
||||
override selectionDeniedText(_pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveCannotBeSelected", { moveName: allMoves[move].name });
|
||||
override selectionDeniedText(pokemon: Pokemon, _move: Moves): string {
|
||||
return i18next.t("battle:moveDisabledTorment", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) });
|
||||
}
|
||||
}
|
||||
|
||||
@ -2559,12 +2559,12 @@ export class TauntTag extends MoveRestrictionBattlerTag {
|
||||
return allMoves[move].category === MoveCategory.STATUS;
|
||||
}
|
||||
|
||||
override selectionDeniedText(_pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveCannotBeSelected", { moveName: allMoves[move].name });
|
||||
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveDisabledTaunt", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
|
||||
override interruptedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledTaunt", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
}
|
||||
|
||||
@ -2609,12 +2609,12 @@ export class ImprisonTag extends MoveRestrictionBattlerTag {
|
||||
return false;
|
||||
}
|
||||
|
||||
override selectionDeniedText(_pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveCannotBeSelected", { moveName: allMoves[move].name });
|
||||
override selectionDeniedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:moveDisabledImprison", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
|
||||
override interruptedText(pokemon: Pokemon, move: Moves): string {
|
||||
return i18next.t("battle:disableInterruptedMove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
return i18next.t("battle:moveDisabledImprison", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: allMoves[move].name });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,21 @@
|
||||
import * as Utils from "../utils";
|
||||
import * as Utils from "#app/utils";
|
||||
import i18next from "i18next";
|
||||
import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data";
|
||||
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species";
|
||||
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import Pokemon, { PokemonMove } from "#app/field/pokemon";
|
||||
import { BattleType, FixedBattleConfig } from "#app/battle";
|
||||
import Trainer, { TrainerVariant } from "#app/field/trainer";
|
||||
import { GameMode } from "#app/game-mode";
|
||||
import { Type } from "./type";
|
||||
import { Type } from "#app/data/type";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { Species } from "#enums/species";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Nature } from "./nature";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { TypeColor, TypeShadow } from "#app/enums/color";
|
||||
import { pokemonEvolutions } from "./pokemon-evolutions";
|
||||
import { pokemonFormChanges } from "./pokemon-forms";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { TypeColor, TypeShadow } from "#enums/color";
|
||||
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
||||
|
||||
/** A constant for the default max cost of the starting party before a run */
|
||||
const DEFAULT_PARTY_MAX_COST = 10;
|
||||
@ -637,7 +638,7 @@ export class FreshStartChallenge extends Challenge {
|
||||
|
||||
applyStarterCost(species: Species, cost: Utils.NumberHolder): boolean {
|
||||
if (defaultStarterSpecies.includes(species)) {
|
||||
cost.value = speciesStarters[species];
|
||||
cost.value = speciesStarterCosts[species];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -719,7 +720,7 @@ export class LowerStarterMaxCostChallenge extends Challenge {
|
||||
}
|
||||
|
||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder): boolean {
|
||||
if (speciesStarters[pokemon.speciesId] > DEFAULT_PARTY_MAX_COST - this.value) {
|
||||
if (speciesStarterCosts[pokemon.speciesId] > DEFAULT_PARTY_MAX_COST - this.value) {
|
||||
valid.value = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { PlayerPokemon } from "../field/pokemon";
|
||||
import { Starter } from "../ui/starter-select-ui-handler";
|
||||
import * as Utils from "../utils";
|
||||
import PokemonSpecies, { PokemonSpeciesForm, getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { Starter } from "#app/ui/starter-select-ui-handler";
|
||||
import * as Utils from "#app/utils";
|
||||
import PokemonSpecies, { PokemonSpeciesForm, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
|
||||
export interface DailyRunConfig {
|
||||
seed: integer;
|
||||
@ -46,9 +47,9 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
|
||||
|
||||
for (let c = 0; c < starterCosts.length; c++) {
|
||||
const cost = starterCosts[c];
|
||||
const costSpecies = Object.keys(speciesStarters)
|
||||
const costSpecies = Object.keys(speciesStarterCosts)
|
||||
.map(s => parseInt(s) as Species)
|
||||
.filter(s => speciesStarters[s] === cost);
|
||||
.filter(s => speciesStarterCosts[s] === cost);
|
||||
const randPkmSpecies = getPokemonSpecies(Utils.randSeedItem(costSpecies));
|
||||
const starterSpecies = getPokemonSpecies(randPkmSpecies.getTrainerSpeciesForLevel(startingLevel, true, PartyMemberStrength.STRONGER));
|
||||
starters.push(getDailyRunStarter(scene, starterSpecies, startingLevel));
|
||||
|
@ -1,30 +1,19 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
||||
import { VariantTier } from "../enums/variant-tier";
|
||||
import * as Utils from "../utils";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { VariantTier } from "#enums/variant-tier";
|
||||
import * as Utils from "#app/utils";
|
||||
import Overrides from "#app/overrides";
|
||||
import { pokemonPrevolutions } from "./pokemon-evolutions";
|
||||
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import i18next from "i18next";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { Species } from "#enums/species";
|
||||
import { EggSourceType } from "#app/enums/egg-source-types";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { MANAPHY_EGG_MANAPHY_RATE, SAME_SPECIES_EGG_HA_RATE, GACHA_EGG_HA_RATE, GACHA_DEFAULT_RARE_EGGMOVE_RATE, SAME_SPECIES_EGG_RARE_EGGMOVE_RATE, GACHA_MOVE_UP_RARE_EGGMOVE_RATE, GACHA_DEFAULT_SHINY_RATE, GACHA_SHINY_UP_SHINY_RATE, SAME_SPECIES_EGG_SHINY_RATE, EGG_PITY_LEGENDARY_THRESHOLD, EGG_PITY_EPIC_THRESHOLD, EGG_PITY_RARE_THRESHOLD, SHINY_VARIANT_CHANCE, SHINY_EPIC_CHANCE, GACHA_DEFAULT_COMMON_EGG_THRESHOLD, GACHA_DEFAULT_RARE_EGG_THRESHOLD, GACHA_DEFAULT_EPIC_EGG_THRESHOLD, GACHA_LEGENDARY_UP_THRESHOLD_OFFSET, HATCH_WAVES_MANAPHY_EGG, HATCH_WAVES_COMMON_EGG, HATCH_WAVES_RARE_EGG, HATCH_WAVES_EPIC_EGG, HATCH_WAVES_LEGENDARY_EGG } from "#app/data/balance/rates";
|
||||
|
||||
export const EGG_SEED = 1073741824;
|
||||
|
||||
// Rates for specific random properties in 1/x
|
||||
const DEFAULT_SHINY_RATE = 128;
|
||||
const GACHA_SHINY_UP_SHINY_RATE = 64;
|
||||
const SAME_SPECIES_EGG_SHINY_RATE = 12;
|
||||
const SAME_SPECIES_EGG_HA_RATE = 8;
|
||||
const MANAPHY_EGG_MANAPHY_RATE = 8;
|
||||
const GACHA_EGG_HA_RATE = 192;
|
||||
|
||||
// 1/x for legendary eggs, 1/x*2 for epic eggs, 1/x*4 for rare eggs, and 1/x*8 for common eggs
|
||||
const DEFAULT_RARE_EGGMOVE_RATE = 6;
|
||||
const SAME_SPECIES_EGG_RARE_EGGMOVE_RATE = 3;
|
||||
const GACHA_MOVE_UP_RARE_EGGMOVE_RATE = 3;
|
||||
|
||||
/** Egg options to override egg properties */
|
||||
export interface IEggOptions {
|
||||
/** Id. Used to check if egg type will be manaphy (id % 204 === 0) */
|
||||
@ -323,7 +312,7 @@ export class Egg {
|
||||
////
|
||||
|
||||
private rollEggMoveIndex() {
|
||||
let baseChance = DEFAULT_RARE_EGGMOVE_RATE;
|
||||
let baseChance = GACHA_DEFAULT_RARE_EGGMOVE_RATE;
|
||||
switch (this._sourceType) {
|
||||
case EggSourceType.SAME_SPECIES_EGG:
|
||||
baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE;
|
||||
@ -341,24 +330,24 @@ export class Egg {
|
||||
|
||||
private getEggTierDefaultHatchWaves(eggTier?: EggTier): number {
|
||||
if (this._species === Species.PHIONE || this._species === Species.MANAPHY) {
|
||||
return 50;
|
||||
return HATCH_WAVES_MANAPHY_EGG;
|
||||
}
|
||||
|
||||
switch (eggTier ?? this._tier) {
|
||||
case EggTier.COMMON:
|
||||
return 10;
|
||||
return HATCH_WAVES_COMMON_EGG;
|
||||
case EggTier.GREAT:
|
||||
return 25;
|
||||
return HATCH_WAVES_RARE_EGG;
|
||||
case EggTier.ULTRA:
|
||||
return 50;
|
||||
return HATCH_WAVES_EPIC_EGG;
|
||||
}
|
||||
return 100;
|
||||
return HATCH_WAVES_LEGENDARY_EGG;
|
||||
}
|
||||
|
||||
private rollEggTier(): EggTier {
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? 1 : 0;
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0;
|
||||
const tierValue = Utils.randInt(256);
|
||||
return tierValue >= 52 + tierValueOffset ? EggTier.COMMON : tierValue >= 8 + tierValueOffset ? EggTier.GREAT : tierValue >= 1 + tierValueOffset ? EggTier.ULTRA : EggTier.MASTER;
|
||||
return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.GREAT : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.ULTRA : EggTier.MASTER;
|
||||
}
|
||||
|
||||
private rollSpecies(scene: BattleScene): Species | null {
|
||||
@ -409,8 +398,8 @@ export class Egg {
|
||||
|
||||
const ignoredSpecies = [Species.PHIONE, Species.MANAPHY, Species.ETERNATUS];
|
||||
|
||||
let speciesPool = Object.keys(speciesStarters)
|
||||
.filter(s => speciesStarters[s] >= minStarterValue && speciesStarters[s] <= maxStarterValue)
|
||||
let speciesPool = Object.keys(speciesStarterCosts)
|
||||
.filter(s => speciesStarterCosts[s] >= minStarterValue && speciesStarterCosts[s] <= maxStarterValue)
|
||||
.map(s => parseInt(s) as Species)
|
||||
.filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1);
|
||||
|
||||
@ -441,7 +430,7 @@ export class Egg {
|
||||
let totalWeight = 0;
|
||||
const speciesWeights : number[] = [];
|
||||
for (const speciesId of speciesPool) {
|
||||
let weight = Math.floor((((maxStarterValue - speciesStarters[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
|
||||
let weight = Math.floor((((maxStarterValue - speciesStarterCosts[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100);
|
||||
const species = getPokemonSpecies(speciesId);
|
||||
if (species.isRegional()) {
|
||||
weight = Math.floor(weight / 2);
|
||||
@ -475,7 +464,7 @@ export class Egg {
|
||||
* @returns True if the egg is shiny
|
||||
**/
|
||||
private rollShiny(): boolean {
|
||||
let shinyChance = DEFAULT_SHINY_RATE;
|
||||
let shinyChance = GACHA_DEFAULT_SHINY_RATE;
|
||||
switch (this._sourceType) {
|
||||
case EggSourceType.GACHA_SHINY:
|
||||
shinyChance = GACHA_SHINY_UP_SHINY_RATE;
|
||||
@ -498,9 +487,9 @@ export class Egg {
|
||||
}
|
||||
|
||||
const rand = Utils.randSeedInt(10);
|
||||
if (rand >= 4) {
|
||||
if (rand >= SHINY_VARIANT_CHANCE) {
|
||||
return VariantTier.STANDARD; // 6/10
|
||||
} else if (rand >= 1) {
|
||||
} else if (rand >= SHINY_EPIC_CHANCE) {
|
||||
return VariantTier.RARE; // 3/10
|
||||
} else {
|
||||
return VariantTier.EPIC; // 1/10
|
||||
@ -508,16 +497,16 @@ export class Egg {
|
||||
}
|
||||
|
||||
private checkForPityTierOverrides(scene: BattleScene): void {
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? 1 : 0;
|
||||
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0;
|
||||
scene.gameData.eggPity[EggTier.GREAT] += 1;
|
||||
scene.gameData.eggPity[EggTier.ULTRA] += 1;
|
||||
scene.gameData.eggPity[EggTier.MASTER] += 1 + tierValueOffset;
|
||||
// These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered.
|
||||
if (scene.gameData.eggPity[EggTier.MASTER] >= 412 && this._tier === EggTier.COMMON) {
|
||||
if (scene.gameData.eggPity[EggTier.MASTER] >= EGG_PITY_LEGENDARY_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.MASTER;
|
||||
} else if (scene.gameData.eggPity[EggTier.ULTRA] >= 59 && this._tier === EggTier.COMMON) {
|
||||
} else if (scene.gameData.eggPity[EggTier.ULTRA] >= EGG_PITY_EPIC_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.ULTRA;
|
||||
} else if (scene.gameData.eggPity[EggTier.GREAT] >= 9 && this._tier === EggTier.COMMON) {
|
||||
} else if (scene.gameData.eggPity[EggTier.GREAT] >= EGG_PITY_RARE_THRESHOLD && this._tier === EggTier.COMMON) {
|
||||
this._tier = EggTier.GREAT;
|
||||
}
|
||||
scene.gameData.eggPity[this._tier] = 0;
|
||||
@ -544,7 +533,7 @@ export class Egg {
|
||||
}
|
||||
|
||||
private getEggTierFromSpeciesStarterValue(): EggTier {
|
||||
const speciesStartValue = speciesStarters[this.species];
|
||||
const speciesStartValue = speciesStarterCosts[this.species];
|
||||
if (speciesStartValue >= 1 && speciesStartValue <= 3) {
|
||||
return EggTier.COMMON;
|
||||
}
|
||||
@ -567,7 +556,7 @@ export class Egg {
|
||||
}
|
||||
|
||||
export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timestamp: number): Species {
|
||||
const legendarySpecies = Object.entries(speciesStarters)
|
||||
const legendarySpecies = Object.entries(speciesStarterCosts)
|
||||
.filter(s => s[1] >= 8 && s[1] <= 9)
|
||||
.map(s => parseInt(s[0]))
|
||||
.filter(s => getPokemonSpecies(s).isObtainable());
|
||||
@ -594,7 +583,7 @@ export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timesta
|
||||
* @returns The egg tier of a given pokemon species
|
||||
*/
|
||||
export function getEggTierForSpecies(pokemonSpecies :PokemonSpecies): EggTier {
|
||||
const speciesBaseValue = speciesStarters[pokemonSpecies.getRootSpeciesId()];
|
||||
const speciesBaseValue = speciesStarterCosts[pokemonSpecies.getRootSpeciesId()];
|
||||
if (speciesBaseValue <= 3) {
|
||||
return EggTier.COMMON;
|
||||
} else if (speciesBaseValue <= 5) {
|
||||
|
106
src/data/move.ts
106
src/data/move.ts
@ -25,7 +25,6 @@ import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { MoveUsedEvent } from "#app/events/battle-scene";
|
||||
import { BATTLE_STATS, type BattleStat, EFFECTIVE_STATS, type EffectiveStat, getStatKey, Stat } from "#app/enums/stat";
|
||||
import { PartyStatusCurePhase } from "#app/phases/party-status-cure-phase";
|
||||
import { BattleEndPhase } from "#app/phases/battle-end-phase";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
@ -34,6 +33,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
import { SpeciesFormChangeRevertWeatherFormTrigger } from "./pokemon-forms";
|
||||
import { GameMode } from "#app/game-mode";
|
||||
import { applyChallenges, ChallengeType } from "./challenge";
|
||||
@ -1585,12 +1585,31 @@ export class PartyStatusCureAttr extends MoveEffectAttr {
|
||||
if (!this.canApply(user, target, move, args)) {
|
||||
return false;
|
||||
}
|
||||
this.addPartyCurePhase(user);
|
||||
const partyPokemon = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty();
|
||||
partyPokemon.forEach(p => this.cureStatus(p, user.id));
|
||||
|
||||
if (this.message) {
|
||||
user.scene.queueMessage(this.message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
addPartyCurePhase(user: Pokemon) {
|
||||
user.scene.unshiftPhase(new PartyStatusCurePhase(user.scene, user, this.message, this.abilityCondition));
|
||||
/**
|
||||
* Tries to cure the status of the given {@linkcode Pokemon}
|
||||
* @param pokemon The {@linkcode Pokemon} to cure.
|
||||
* @param userId The ID of the (move) {@linkcode Pokemon | user}.
|
||||
*/
|
||||
public cureStatus(pokemon: Pokemon, userId: number) {
|
||||
if (!pokemon.isOnField() || pokemon.id === userId) { // user always cures its own status, regardless of ability
|
||||
pokemon.resetStatus(false);
|
||||
pokemon.updateInfo();
|
||||
} else if (!pokemon.hasAbility(this.abilityCondition)) {
|
||||
pokemon.resetStatus();
|
||||
pokemon.updateInfo();
|
||||
} else {
|
||||
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, pokemon.getPassiveAbility()?.id === this.abilityCondition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2668,20 +2687,42 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for moves that change stat stages
|
||||
* @param stats {@linkcode BattleStat} array of stats to be changed
|
||||
* @param stages stages by which to change the stats, from -6 to 6
|
||||
* @param selfTarget whether the changes are applied to the user (true) or the target (false)
|
||||
* @param condition {@linkcode MoveConditionFunc} optional condition to trigger the stat change
|
||||
* @param firstHitOnly whether the stat change only applies on the first hit of a multi hit move
|
||||
* @param moveEffectTrigger {@linkcode MoveEffectTrigger} the trigger for the effect to take place
|
||||
* @param firstTargetOnly whether, if this is a multi target move, to only apply the effect after the first target is hit, rather than once for each target
|
||||
* @param lastHitOnly whether the effect should only apply after the last hit of a multi hit move
|
||||
*
|
||||
* @extends MoveEffectAttr
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class StatStageChangeAttr extends MoveEffectAttr {
|
||||
public stats: BattleStat[];
|
||||
public stages: integer;
|
||||
private condition: MoveConditionFunc | null;
|
||||
private showMessage: boolean;
|
||||
|
||||
constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false) {
|
||||
super(selfTarget, moveEffectTrigger, firstHitOnly, false, firstTargetOnly);
|
||||
constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false, lastHitOnly: boolean = false) {
|
||||
super(selfTarget, moveEffectTrigger, firstHitOnly, lastHitOnly, firstTargetOnly);
|
||||
this.stats = stats;
|
||||
this.stages = stages;
|
||||
this.condition = condition!; // TODO: is this bang correct?
|
||||
this.showMessage = showMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to change stats of the user or target (depending on value of selfTarget) if conditions are met
|
||||
* @param user {@linkcode Pokemon} the user of the move
|
||||
* @param target {@linkcode Pokemon} the target of the move
|
||||
* @param move {@linkcode Move} the move
|
||||
* @param args unused
|
||||
* @returns whether stat stages were changed
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean | Promise<boolean> {
|
||||
if (!super.apply(user, target, move, args) || (this.condition && !this.condition(user, target, move))) {
|
||||
return false;
|
||||
@ -3901,7 +3942,14 @@ export class PhotonGeyserCategoryAttr extends VariableMoveCategoryAttr {
|
||||
}
|
||||
}
|
||||
|
||||
export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr {
|
||||
/**
|
||||
* Attribute used for tera moves that change category based on the user's Atk and SpAtk stats
|
||||
* Note: Currently, `getEffectiveStat` does not ignore all abilities that affect stats except those
|
||||
* with the attribute of `StatMultiplierAbAttr`
|
||||
* TODO: Remove the `.partial()` tag from Tera Blast and Tera Starstorm when the above issue is resolved
|
||||
* @extends VariableMoveCategoryAttr
|
||||
*/
|
||||
export class TeraMoveCategoryAttr extends VariableMoveCategoryAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const category = (args[0] as Utils.NumberHolder);
|
||||
|
||||
@ -3990,6 +4038,30 @@ export class VariableMoveTypeAttr extends MoveAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for Tera Starstorm that changes the move type to Stellar
|
||||
* @extends VariableMoveTypeAttr
|
||||
*/
|
||||
export class TeraStarstormTypeAttr extends VariableMoveTypeAttr {
|
||||
/**
|
||||
*
|
||||
* @param user the {@linkcode Pokemon} using the move
|
||||
* @param target n/a
|
||||
* @param move n/a
|
||||
* @param args[0] {@linkcode Utils.NumberHolder} the move type
|
||||
* @returns `true` if the move type is changed to {@linkcode Type.STELLAR}, `false` otherwise
|
||||
*/
|
||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (user.isTerastallized() && (user.hasFusionSpecies(Species.TERAPAGOS) || user.species.speciesId === Species.TERAPAGOS)) {
|
||||
const moveType = args[0] as Utils.NumberHolder;
|
||||
|
||||
moveType.value = Type.STELLAR;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const moveType = args[0];
|
||||
@ -9149,16 +9221,15 @@ export function initMoves() {
|
||||
.attr(HalfSacrificialAttr),
|
||||
new AttackMove(Moves.EXPANDING_FORCE, Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 8)
|
||||
.attr(MovePowerMultiplierAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.PSYCHIC && user.isGrounded() ? 1.5 : 1)
|
||||
.attr(VariableTargetAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.PSYCHIC && user.isGrounded() ? 6 : 3),
|
||||
.attr(VariableTargetAttr, (user, target, move) => user.scene.arena.getTerrainType() === TerrainType.PSYCHIC && user.isGrounded() ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER),
|
||||
new AttackMove(Moves.STEEL_ROLLER, Type.STEEL, MoveCategory.PHYSICAL, 130, 100, 5, -1, 0, 8)
|
||||
.attr(ClearTerrainAttr)
|
||||
.condition((user, target, move) => !!user.scene.arena.terrain),
|
||||
new AttackMove(Moves.SCALE_SHOT, Type.DRAGON, MoveCategory.PHYSICAL, 25, 90, 20, -1, 0, 8)
|
||||
//.attr(StatStageChangeAttr, Stat.SPD, 1, true) // TODO: Have boosts only apply at end of move, not after every hit
|
||||
//.attr(StatStageChangeAttr, Stat.DEF, -1, true)
|
||||
.attr(StatStageChangeAttr, [Stat.SPD], 1, true, null, true, false, MoveEffectTrigger.HIT, false, true)
|
||||
.attr(StatStageChangeAttr, [Stat.DEF], -1, true, null, true, false, MoveEffectTrigger.HIT, false, true)
|
||||
.attr(MultiHitAttr)
|
||||
.makesContact(false)
|
||||
.partial(),
|
||||
.makesContact(false),
|
||||
new AttackMove(Moves.METEOR_BEAM, Type.ROCK, MoveCategory.SPECIAL, 120, 90, 10, 100, 0, 8)
|
||||
.attr(ChargeAttr, ChargeAnim.METEOR_BEAM_CHARGING, i18next.t("moveTriggers:isOverflowingWithSpacePower", {pokemonName: "{USER}"}), null, true)
|
||||
.attr(StatStageChangeAttr, [ Stat.SPATK ], 1, true)
|
||||
@ -9424,10 +9495,11 @@ export function initMoves() {
|
||||
.unimplemented(),
|
||||
End Unused */
|
||||
new AttackMove(Moves.TERA_BLAST, Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 9)
|
||||
.attr(TeraBlastCategoryAttr)
|
||||
.attr(TeraMoveCategoryAttr)
|
||||
.attr(TeraBlastTypeAttr)
|
||||
.attr(TeraBlastPowerAttr)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR)),
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR))
|
||||
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
|
||||
new SelfStatusMove(Moves.SILK_TRAP, Type.BUG, -1, 10, -1, 4, 9)
|
||||
.attr(ProtectAttr, BattlerTagType.SILK_TRAP)
|
||||
.condition(failIfLastCondition),
|
||||
@ -9617,8 +9689,10 @@ export function initMoves() {
|
||||
.attr(ElectroShotChargeAttr)
|
||||
.ignoresVirtual(),
|
||||
new AttackMove(Moves.TERA_STARSTORM, Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9)
|
||||
.attr(TeraBlastCategoryAttr)
|
||||
.partial(),
|
||||
.attr(TeraMoveCategoryAttr)
|
||||
.attr(TeraStarstormTypeAttr)
|
||||
.attr(VariableTargetAttr, (user, target, move) => (user.hasFusionSpecies(Species.TERAPAGOS) || user.species.speciesId === Species.TERAPAGOS) && user.isTerastallized() ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER)
|
||||
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
|
||||
new AttackMove(Moves.FICKLE_BEAM, Type.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9)
|
||||
.attr(PreMoveMessageAttr, doublePowerChanceMessageFunc)
|
||||
.attr(DoublePowerChanceAttr),
|
||||
|
@ -8,7 +8,8 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
|
||||
import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||
@ -72,7 +73,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter =
|
||||
const pokemon = getHighestStatTotalPlayerPokemon(scene, true, true);
|
||||
|
||||
const baseSpecies = pokemon.getSpeciesForm().getRootSpeciesId();
|
||||
const starterValue: number = speciesStarters[baseSpecies] ?? 1;
|
||||
const starterValue: number = speciesStarterCosts[baseSpecies] ?? 1;
|
||||
const multiplier = Math.max(MONEY_MAXIMUM_MULTIPLIER / 10 * starterValue, MONEY_MINIMUM_MULTIPLIER);
|
||||
const price = scene.getWaveMoneyAmount(multiplier);
|
||||
|
||||
|
@ -10,7 +10,8 @@ import { Biome } from "#enums/biome";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import i18next from "i18next";
|
||||
import { Species } from "#enums/species";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
@ -454,8 +455,8 @@ function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number]
|
||||
const rootSpecies = pokemon.species.getRootSpeciesId();
|
||||
let pointsFromStarterTier = 0;
|
||||
// 2 points for every 1 below 7 that the pokemon's starter tier is (max 12, min 0)
|
||||
if (speciesStarters.hasOwnProperty(rootSpecies)) {
|
||||
const starterTier = speciesStarters[rootSpecies];
|
||||
if (speciesStarterCosts.hasOwnProperty(rootSpecies)) {
|
||||
const starterTier = speciesStarterCosts[rootSpecies];
|
||||
pointsFromStarterTier = Math.min(Math.max(Math.floor(7 - starterTier) * 2, 0), 12);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ import BattleScene from "#app/battle-scene";
|
||||
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
import { catchPokemon, getRandomSpeciesByStarterTier, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { Species } from "#enums/species";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
||||
@ -88,7 +89,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter =
|
||||
isPokemon: true
|
||||
});
|
||||
|
||||
const starterTier = speciesStarters[species.speciesId];
|
||||
const starterTier = speciesStarterCosts[species.speciesId];
|
||||
// Prices decrease by starter tier less than 5, but only reduces cost by half at max
|
||||
let priceMultiplier = MAX_POKEMON_PRICE_MULTIPLIER * (Math.max(starterTier, 2.5) / 5);
|
||||
if (pokemon.shiny) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Ability, allAbilities } from "#app/data/ability";
|
||||
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { getNatureName, Nature } from "#app/data/nature";
|
||||
import { speciesStarters } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { AbilityAttr } from "#app/system/game-data";
|
||||
@ -326,7 +326,7 @@ export const TrainingSessionEncounter: MysteryEncounter =
|
||||
// Only update the fusion's dex data if the Pokemon is already caught in dex (ignore rentals)
|
||||
const rootFusionSpecies = playerPokemon.fusionSpecies?.getRootSpeciesId();
|
||||
if (!isNullOrUndefined(rootFusionSpecies)
|
||||
&& speciesStarters.hasOwnProperty(rootFusionSpecies)
|
||||
&& speciesStarterCosts.hasOwnProperty(rootFusionSpecies)
|
||||
&& !!scene.gameData.dexData[rootFusionSpecies].caughtAttr) {
|
||||
scene.gameData.starterData[rootFusionSpecies].abilityAttr |= playerPokemon.fusionAbilityIndex !== 1 || playerPokemon.fusionSpecies?.ability2
|
||||
? 1 << playerPokemon.fusionAbilityIndex
|
||||
|
@ -5,12 +5,12 @@ import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { TimeOfDay } from "#enums/time-of-day";
|
||||
import { Nature } from "../nature";
|
||||
import { EvolutionItem, pokemonEvolutions } from "../pokemon-evolutions";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "../pokemon-forms";
|
||||
import { StatusEffect } from "../status-effect";
|
||||
import { Type } from "../type";
|
||||
import { WeatherType } from "../weather";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import { Type } from "#app/data/type";
|
||||
import { WeatherType } from "#app/data/weather";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
|
||||
import { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
|
||||
|
@ -32,7 +32,7 @@ import { FunAndGamesEncounter } from "#app/data/mystery-encounters/encounters/fu
|
||||
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter";
|
||||
import { GlobalTradeSystemEncounter } from "#app/data/mystery-encounters/encounters/global-trade-system-encounter";
|
||||
import { TheExpertPokemonBreederEncounter } from "#app/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter";
|
||||
import { getBiomeName } from "#app/data/biomes";
|
||||
import { getBiomeName } from "#app/data/balance/biomes";
|
||||
|
||||
/**
|
||||
* Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT
|
||||
@ -363,6 +363,7 @@ export function initMysteryEncounters() {
|
||||
});
|
||||
|
||||
// Add ANY biome encounters to biome map
|
||||
// eslint-disable-next-line
|
||||
let encounterBiomeTableLog = "";
|
||||
mysteryEncountersByBiome.forEach((biomeEncounters, biome) => {
|
||||
anyBiomeEncounters.forEach(encounter => {
|
||||
@ -374,5 +375,5 @@ export function initMysteryEncounters() {
|
||||
encounterBiomeTableLog += `${getBiomeName(biome).toUpperCase()}: [${biomeEncounters.map(type => MysteryEncounterType[type].toString().toLowerCase()).sort().join(", ")}]\n`;
|
||||
});
|
||||
|
||||
console.debug("All Mystery Encounters by Biome:\n" + encounterBiomeTableLog);
|
||||
//console.debug("All Mystery Encounters by Biome:\n" + encounterBiomeTableLog);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Battle, { BattlerIndex, BattleType } from "#app/battle";
|
||||
import { biomeLinks, BiomePoolTier } from "#app/data/biomes";
|
||||
import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes";
|
||||
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
|
@ -12,7 +12,8 @@ import { Mode } from "#app/ui/ui";
|
||||
import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
|
||||
import { Species } from "#enums/species";
|
||||
import { Type } from "#app/data/type";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { getEncounterText, queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
@ -208,8 +209,8 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu
|
||||
let min = Array.isArray(starterTiers) ? starterTiers[0] : starterTiers;
|
||||
let max = Array.isArray(starterTiers) ? starterTiers[1] : starterTiers;
|
||||
|
||||
let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarters)
|
||||
.map(s => [parseInt(s) as Species, speciesStarters[s] as number])
|
||||
let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarterCosts)
|
||||
.map(s => [parseInt(s) as Species, speciesStarterCosts[s] as number])
|
||||
.filter(s => {
|
||||
const pokemonSpecies = getPokemonSpecies(s[0]);
|
||||
return pokemonSpecies && (!excludedSpecies || !excludedSpecies.includes(s[0]))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,22 +1,22 @@
|
||||
import BattleScene, { startingWave } from "../battle-scene";
|
||||
import { ModifierTypeFunc, modifierTypes } from "../modifier/modifier-type";
|
||||
import { EnemyPokemon, PokemonMove } from "../field/pokemon";
|
||||
import * as Utils from "../utils";
|
||||
import { PokeballType } from "./pokeball";
|
||||
import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
|
||||
import PokemonSpecies, { getPokemonSpecies, PokemonSpeciesFilter } from "./pokemon-species";
|
||||
import { tmSpecies } from "./tms";
|
||||
import { Type } from "./type";
|
||||
import { doubleBattleDialogue } from "./dialogue";
|
||||
import { PersistentModifier } from "../modifier/modifier";
|
||||
import { TrainerVariant } from "../field/trainer";
|
||||
import BattleScene, { startingWave } from "#app/battle-scene";
|
||||
import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import * as Utils from "#app/utils";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import PokemonSpecies, { getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species";
|
||||
import { tmSpecies } from "#app/data/balance/tms";
|
||||
import { Type } from "#app/data/type";
|
||||
import { doubleBattleDialogue } from "#app/data/dialogue";
|
||||
import { PersistentModifier } from "#app/modifier/modifier";
|
||||
import { TrainerVariant } from "#app/field/trainer";
|
||||
import { getIsInitialized, initI18n } from "#app/plugins/i18n";
|
||||
import i18next from "i18next";
|
||||
import {Moves} from "#enums/moves";
|
||||
import {PartyMemberStrength} from "#enums/party-member-strength";
|
||||
import {Species} from "#enums/species";
|
||||
import {TrainerType} from "#enums/trainer-type";
|
||||
import {Gender} from "./gender";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Gender } from "#app/data/gender";
|
||||
|
||||
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
||||
const ELITE_FOUR_MINIMUM_BST = 460;
|
||||
|
@ -1,26 +1,26 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { biomePokemonPools, BiomePoolTier, BiomeTierTrainerPools, biomeTrainerPools, PokemonPools } from "../data/biomes";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { biomePokemonPools, BiomePoolTier, BiomeTierTrainerPools, biomeTrainerPools, PokemonPools } from "#app/data/balance/biomes";
|
||||
import { Constructor } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "../data/pokemon-species";
|
||||
import { getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage, Weather, WeatherType } from "../data/weather";
|
||||
import { CommonAnim } from "../data/battle-anims";
|
||||
import { Type } from "../data/type";
|
||||
import Move from "../data/move";
|
||||
import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "../data/arena-tag";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { Terrain, TerrainType } from "../data/terrain";
|
||||
import { applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs, PostTerrainChangeAbAttr, PostWeatherChangeAbAttr } from "../data/ability";
|
||||
import Pokemon from "./pokemon";
|
||||
import * as Utils from "#app/utils";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage, Weather, WeatherType } from "#app/data/weather";
|
||||
import { CommonAnim } from "#app/data/battle-anims";
|
||||
import { Type } from "#app/data/type";
|
||||
import Move from "#app/data/move";
|
||||
import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "#app/data/arena-tag";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { Terrain, TerrainType } from "#app/data/terrain";
|
||||
import { applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs, PostTerrainChangeAbAttr, PostWeatherChangeAbAttr } from "#app/data/ability";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import Overrides from "#app/overrides";
|
||||
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "../events/arena";
|
||||
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import { Biome } from "#enums/biome";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { TimeOfDay } from "#enums/time-of-day";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms";
|
||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
||||
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
|
@ -1,43 +1,45 @@
|
||||
import Phaser from "phaser";
|
||||
import BattleScene, { AnySound } from "../battle-scene";
|
||||
import BattleScene, { AnySound } from "#app/battle-scene";
|
||||
import { Variant, VariantSet, variantColorCache } from "#app/data/variant";
|
||||
import { variantData } from "#app/data/variant";
|
||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info";
|
||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget } from "../data/move";
|
||||
import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species";
|
||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info";
|
||||
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget } from "#app/data/move";
|
||||
import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
||||
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type";
|
||||
import { getLevelTotalExp } from "../data/exp";
|
||||
import * as Utils from "#app/utils";
|
||||
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "#app/data/type";
|
||||
import { getLevelTotalExp } from "#app/data/exp";
|
||||
import { Stat, type PermanentStat, type BattleStat, type EffectiveStat, PERMANENT_STATS, BATTLE_STATS, EFFECTIVE_STATS } from "#enums/stat";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, EvoTrackerModifier } from "../modifier/modifier";
|
||||
import { PokeballType } from "../data/pokeball";
|
||||
import { Gender } from "../data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
|
||||
import { Status, StatusEffect, getRandomStatus } from "../data/status-effect";
|
||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "../data/pokemon-evolutions";
|
||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "../data/tms";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, EvoTrackerModifier } from "#app/modifier/modifier";
|
||||
import { PokeballType } from "#app/data/pokeball";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
||||
import { Status, StatusEffect, getRandomStatus } from "#app/data/status-effect";
|
||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#app/data/balance/tms";
|
||||
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, SubstituteTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag, AutotomizedTag } from "../data/battler-tags";
|
||||
import { WeatherType } from "../data/weather";
|
||||
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
|
||||
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs } from "../data/ability";
|
||||
import PokemonData from "../system/pokemon-data";
|
||||
import { BattlerIndex } from "../battle";
|
||||
import { Mode } from "../ui/ui";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "../ui/party-ui-handler";
|
||||
import { WeatherType } from "#app/data/weather";
|
||||
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag";
|
||||
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs } from "#app/data/ability";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { LevelMoves } from "../data/pokemon-level-moves";
|
||||
import { DamageAchv, achvs } from "../system/achv";
|
||||
import { DexAttr, StarterDataEntry, StarterMoveset } from "../system/game-data";
|
||||
import { LevelMoves } from "#app/data/balance/pokemon-level-moves";
|
||||
import { DamageAchv, achvs } from "#app/system/achv";
|
||||
import { DexAttr, StarterDataEntry, StarterMoveset } from "#app/system/game-data";
|
||||
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
import { Nature, getNatureStatMultiplier } from "../data/nature";
|
||||
import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "../data/pokemon-forms";
|
||||
import { TerrainType } from "../data/terrain";
|
||||
import { TrainerSlot } from "../data/trainer-config";
|
||||
import { Nature, getNatureStatMultiplier } from "#app/data/nature";
|
||||
import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms";
|
||||
import { TerrainType } from "#app/data/terrain";
|
||||
import { TrainerSlot } from "#app/data/trainer-config";
|
||||
import Overrides from "#app/overrides";
|
||||
import i18next from "i18next";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { ModifierTier } from "../modifier/modifier-tier";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
@ -58,17 +60,12 @@ import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { PokemonAnimType } from "#app/enums/pokemon-anim-type";
|
||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
||||
import { CustomPokemonData } from "#app/data/mystery-encounters/custom-pokemon-data";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
|
||||
/** `64/65536 -> 1/1024` */
|
||||
const BASE_SHINY_CHANCE = 64;
|
||||
|
||||
/** `1/256` */
|
||||
const BASE_HIDDEN_ABILITY_CHANCE = 256;
|
||||
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
|
||||
|
||||
export enum FieldPosition {
|
||||
CENTER,
|
||||
@ -1086,6 +1083,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return !!this.fusionSpecies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@linkcode Pokemon} has a fusion with the specified {@linkcode Species}.
|
||||
* @param species the pokemon {@linkcode Species} to check
|
||||
* @returns `true` if the {@linkcode Pokemon} has a fusion with the specified {@linkcode Species}, `false` otherwise
|
||||
*/
|
||||
hasFusionSpecies(species: Species): boolean {
|
||||
return this.fusionSpecies?.speciesId === species;
|
||||
}
|
||||
|
||||
abstract isBoss(): boolean;
|
||||
|
||||
getMoveset(ignoreOverride?: boolean): (PokemonMove | null)[] {
|
||||
@ -1534,6 +1540,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @returns The type damage multiplier, indicating the effectiveness of the move
|
||||
*/
|
||||
getMoveEffectiveness(source: Pokemon, move: Move, ignoreAbility: boolean = false, simulated: boolean = true, cancelled?: Utils.BooleanHolder): TypeDamageMultiplier {
|
||||
if (!Utils.isNullOrUndefined(this.turnData?.moveEffectiveness)) {
|
||||
return this.turnData?.moveEffectiveness;
|
||||
}
|
||||
|
||||
if (move.hasAttr(TypelessAttr)) {
|
||||
return 1;
|
||||
}
|
||||
@ -1922,9 +1932,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.scene.executeWithSeedOffset(() => {
|
||||
rand.value = Utils.randSeedInt(10);
|
||||
}, this.id, this.scene.waveSeed);
|
||||
if (rand.value >= 4) {
|
||||
if (rand.value >= SHINY_VARIANT_CHANCE) {
|
||||
return 0; // 6/10
|
||||
} else if (rand.value >= 1) {
|
||||
} else if (rand.value >= SHINY_EPIC_CHANCE) {
|
||||
return 1; // 3/10
|
||||
} else {
|
||||
return 2; // 1/10
|
||||
@ -4049,7 +4059,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
starterData.forEach((sd: StarterDataEntry, i: integer) => {
|
||||
const speciesId = !i ? starterSpeciesId : fusionStarterSpeciesId as Species;
|
||||
sd.friendship = (sd.friendship || 0) + starterAmount.value;
|
||||
if (sd.friendship >= getStarterValueFriendshipCap(speciesStarters[speciesId])) {
|
||||
if (sd.friendship >= getStarterValueFriendshipCap(speciesStarterCosts[speciesId])) {
|
||||
this.scene.gameData.addStarterCandy(getPokemonSpecies(speciesId), 1);
|
||||
sd.friendship = 0;
|
||||
}
|
||||
@ -5014,6 +5024,7 @@ export class PokemonTurnData {
|
||||
public order: number;
|
||||
public statStagesIncreased: boolean = false;
|
||||
public statStagesDecreased: boolean = false;
|
||||
public moveEffectiveness: TypeDamageMultiplier | null = null;
|
||||
}
|
||||
|
||||
export enum AiType {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import {pokemonPrevolutions} from "../data/pokemon-evolutions";
|
||||
import PokemonSpecies, {getPokemonSpecies} from "../data/pokemon-species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import {pokemonPrevolutions} from "#app/data/balance/pokemon-evolutions";
|
||||
import PokemonSpecies, {getPokemonSpecies} from "#app/data/pokemon-species";
|
||||
import {
|
||||
TrainerConfig,
|
||||
TrainerPartyCompoundTemplate,
|
||||
@ -10,13 +10,13 @@ import {
|
||||
trainerConfigs,
|
||||
trainerPartyTemplates,
|
||||
signatureSpecies
|
||||
} from "../data/trainer-config";
|
||||
import {EnemyPokemon} from "./pokemon";
|
||||
import * as Utils from "../utils";
|
||||
import {PersistentModifier} from "../modifier/modifier";
|
||||
import {trainerNamePools} from "../data/trainer-names";
|
||||
import {ArenaTagSide, ArenaTrapTag} from "#app/data/arena-tag";
|
||||
import {getIsInitialized, initI18n} from "#app/plugins/i18n";
|
||||
} from "#app/data/trainer-config";
|
||||
import {EnemyPokemon} from "#app/field/pokemon";
|
||||
import * as Utils from "#app/utils";
|
||||
import { PersistentModifier } from "#app/modifier/modifier";
|
||||
import { trainerNamePools } from "#app/data/trainer-names";
|
||||
import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag";
|
||||
import { getIsInitialized, initI18n } from "#app/plugins/i18n";
|
||||
import i18next from "i18next";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
|
@ -1,23 +1,23 @@
|
||||
import { GachaType } from "./enums/gacha-types";
|
||||
import { getBiomeHasProps } from "./field/arena";
|
||||
import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin";
|
||||
import { SceneBase } from "./scene-base";
|
||||
import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme";
|
||||
import { isMobile } from "./touch-controls";
|
||||
import * as Utils from "./utils";
|
||||
import { initPokemonPrevolutions } from "#app/data/pokemon-evolutions";
|
||||
import { initBiomes } from "#app/data/biomes";
|
||||
import { initEggMoves } from "#app/data/egg-moves";
|
||||
import { GachaType } from "#enums/gacha-types";
|
||||
import { getBiomeHasProps } from "#app/field/arena";
|
||||
import CacheBustedLoaderPlugin from "#app/plugins/cache-busted-loader-plugin";
|
||||
import { SceneBase } from "#app/scene-base";
|
||||
import { WindowVariant, getWindowVariantSuffix } from "#app/ui/ui-theme";
|
||||
import { isMobile } from "#app/touch-controls";
|
||||
import * as Utils from "#app/utils";
|
||||
import { initPokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { initBiomes } from "#app/data/balance/biomes";
|
||||
import { initEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { initPokemonForms } from "#app/data/pokemon-forms";
|
||||
import { initSpecies } from "#app/data/pokemon-species";
|
||||
import { initMoves } from "#app/data/move";
|
||||
import { initAbilities } from "#app/data/ability";
|
||||
import { initAchievements } from "#app/system/achv";
|
||||
import { initTrainerTypeDialogue } from "#app/data/dialogue";
|
||||
import { initChallenges } from "./data/challenge";
|
||||
import { initChallenges } from "#app/data/challenge";
|
||||
import i18next from "i18next";
|
||||
import { initStatsKeys } from "./ui/game-stats-ui-handler";
|
||||
import { initVouchers } from "./system/voucher";
|
||||
import { initStatsKeys } from "#app/ui/game-stats-ui-handler";
|
||||
import { initVouchers } from "#app/system/voucher";
|
||||
import { Biome } from "#enums/biome";
|
||||
import {initMysteryEncounters} from "#app/data/mystery-encounters/mystery-encounters";
|
||||
|
||||
@ -44,6 +44,8 @@ export class LoadingScene extends SceneBase {
|
||||
this.loadAtlas("prompt", "ui");
|
||||
this.loadImage("candy", "ui");
|
||||
this.loadImage("candy_overlay", "ui");
|
||||
this.loadImage("friendship", "ui");
|
||||
this.loadImage("friendship_overlay", "ui");
|
||||
this.loadImage("cursor", "ui");
|
||||
this.loadImage("cursor_reverse", "ui");
|
||||
for (const wv of Utils.getEnumValues(WindowVariant)) {
|
||||
|
@ -1,38 +1,35 @@
|
||||
import * as Modifiers from "./modifier";
|
||||
import { MoneyMultiplierModifier } from "./modifier";
|
||||
import { allMoves, AttackMove, selfStatLowerMoves } from "../data/move";
|
||||
import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS, PokeballType } from "../data/pokeball";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { EvolutionItem, pokemonEvolutions } from "../data/pokemon-evolutions";
|
||||
import { tmPoolTiers, tmSpecies } from "../data/tms";
|
||||
import { Type } from "../data/type";
|
||||
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "../ui/party-ui-handler";
|
||||
import * as Utils from "../utils";
|
||||
import { getBerryEffectDescription, getBerryName } from "../data/berry";
|
||||
import { Unlockables } from "../system/unlockables";
|
||||
import { getStatusEffectDescriptor, StatusEffect } from "../data/status-effect";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "../system/voucher";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeCondition, SpeciesFormChangeItemTrigger } from "../data/pokemon-forms";
|
||||
import { ModifierTier } from "./modifier-tier";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { tmPoolTiers, tmSpecies } from "#app/data/balance/tms";
|
||||
import { getBerryEffectDescription, getBerryName } from "#app/data/berry";
|
||||
import { allMoves, AttackMove, selfStatLowerMoves } from "#app/data/move";
|
||||
import { getNatureName, getNatureStatMultiplier, Nature } from "#app/data/nature";
|
||||
import i18next from "i18next";
|
||||
import { getModifierTierTextTint } from "#app/ui/text";
|
||||
import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS, PokeballType } from "#app/data/pokeball";
|
||||
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeCondition, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
||||
import { getStatusEffectDescriptor, StatusEffect } from "#app/data/status-effect";
|
||||
import { Type } from "#app/data/type";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { AddPokeballModifier, AddVoucherModifier, AttackTypeBoosterModifier, BaseStatModifier, BerryModifier, BoostBugSpawnModifier, BypassSpeedChanceModifier, ContactHeldItemTransferChanceModifier, CritBoosterModifier, DamageMoneyRewardModifier, DoubleBattleChanceBoosterModifier, EnemyAttackStatusEffectChanceModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, EvolutionItemModifier, EvolutionStatBoosterModifier, EvoTrackerModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, GigantamaxAccessModifier, HealingBoosterModifier, HealShopCostModifier, HiddenAbilityRateBoosterModifier, HitHealModifier, IvScannerModifier, LevelIncrementBoosterModifier, LockModifierTiersModifier, MapModifier, MegaEvolutionAccessModifier, MoneyInterestModifier, MoneyMultiplierModifier, MoneyRewardModifier, MultipleParticipantExpBonusModifier, PokemonAllMovePpRestoreModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, PokemonInstantReviveModifier, PokemonLevelIncrementModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PokemonNatureChangeModifier, PokemonNatureWeightModifier, PokemonPpRestoreModifier, PokemonPpUpModifier, PokemonStatusHealModifier, PreserveBerryModifier, RememberMoveModifier, ResetNegativeStatStageModifier, ShinyRateBoosterModifier, SpeciesCritBoosterModifier, SpeciesStatBoosterModifier, SurviveDamageModifier, SwitchEffectTransferModifier, TempCritBoosterModifier, TempStatStageBoosterModifier, TerastallizeAccessModifier, TerastallizeModifier, TmModifier, TurnHealModifier, TurnHeldItemTransferModifier, TurnStatusEffectModifier, type EnemyPersistentModifier, type Modifier, type PersistentModifier } from "#app/modifier/modifier";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import Overrides from "#app/overrides";
|
||||
import { Unlockables } from "#app/system/unlockables";
|
||||
import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "#app/system/voucher";
|
||||
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||
import { getModifierTierTextTint } from "#app/ui/text";
|
||||
import { formatMoney, getEnumKeys, getEnumValues, IntegerHolder, NumberHolder, padInt, randSeedInt, randSeedItem } from "#app/utils";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { PermanentStat, TEMP_BATTLE_STATS, TempBattleStat, Stat, getStatKey } from "#app/enums/stat";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
import { getStatKey, PermanentStat, Stat, TEMP_BATTLE_STATS, TempBattleStat } from "#enums/stat";
|
||||
import i18next from "i18next";
|
||||
|
||||
const outputModifierData = false;
|
||||
const useMaxWeightForOutput = false;
|
||||
|
||||
type Modifier = Modifiers.Modifier;
|
||||
|
||||
export enum ModifierPoolType {
|
||||
PLAYER,
|
||||
WILD,
|
||||
@ -97,7 +94,7 @@ export class ModifierType {
|
||||
// Try multiple pool types in case of stolen items
|
||||
for (const type of poolTypes) {
|
||||
const pool = getModifierPoolForType(type);
|
||||
for (const tier of Utils.getEnumValues(ModifierTier)) {
|
||||
for (const tier of getEnumValues(ModifierTier)) {
|
||||
if (!pool.hasOwnProperty(tier)) {
|
||||
continue;
|
||||
}
|
||||
@ -171,7 +168,7 @@ class AddPokeballModifierType extends ModifierType {
|
||||
private count: integer;
|
||||
|
||||
constructor(iconImage: string, pokeballType: PokeballType, count: integer) {
|
||||
super("", iconImage, (_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), "pb", "se/pb_bounce_1");
|
||||
super("", iconImage, (_type, _args) => new AddPokeballModifier(this, pokeballType, count), "pb", "se/pb_bounce_1");
|
||||
this.pokeballType = pokeballType;
|
||||
this.count = count;
|
||||
}
|
||||
@ -198,7 +195,7 @@ class AddVoucherModifierType extends ModifierType {
|
||||
private count: integer;
|
||||
|
||||
constructor(voucherType: VoucherType, count: integer) {
|
||||
super("", getVoucherTypeIcon(voucherType), (_type, _args) => new Modifiers.AddVoucherModifier(this, voucherType, count), "voucher");
|
||||
super("", getVoucherTypeIcon(voucherType), (_type, _args) => new AddVoucherModifier(this, voucherType, count), "voucher");
|
||||
this.count = count;
|
||||
this.voucherType = voucherType;
|
||||
}
|
||||
@ -232,7 +229,7 @@ export class PokemonHeldItemModifierType extends PokemonModifierType {
|
||||
constructor(localeKey: string, iconImage: string, newModifierFunc: NewModifierFunc, group?: string, soundName?: string) {
|
||||
super(localeKey, iconImage, newModifierFunc, (pokemon: PlayerPokemon) => {
|
||||
const dummyModifier = this.newModifier(pokemon);
|
||||
const matchingModifier = pokemon.scene.findModifier(m => m instanceof Modifiers.PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(dummyModifier)) as Modifiers.PokemonHeldItemModifier;
|
||||
const matchingModifier = pokemon.scene.findModifier(m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(dummyModifier)) as PokemonHeldItemModifier;
|
||||
const maxStackCount = dummyModifier.getMaxStackCount(pokemon.scene);
|
||||
if (!maxStackCount) {
|
||||
return i18next.t("modifierType:ModifierType.PokemonHeldItemModifierType.extra.inoperable", { "pokemonName": getPokemonNameWithAffix(pokemon) });
|
||||
@ -244,8 +241,8 @@ export class PokemonHeldItemModifierType extends PokemonModifierType {
|
||||
}, group, soundName);
|
||||
}
|
||||
|
||||
newModifier(...args: any[]): Modifiers.PokemonHeldItemModifier {
|
||||
return super.newModifier(...args) as Modifiers.PokemonHeldItemModifier;
|
||||
newModifier(...args: any[]): PokemonHeldItemModifier {
|
||||
return super.newModifier(...args) as PokemonHeldItemModifier;
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,7 +252,7 @@ export class PokemonHpRestoreModifierType extends PokemonModifierType {
|
||||
protected healStatus: boolean;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, group?: string) {
|
||||
super(localeKey, iconImage, newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)),
|
||||
super(localeKey, iconImage, newModifierFunc || ((_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)),
|
||||
selectFilter || ((pokemon: PlayerPokemon) => {
|
||||
if (!pokemon.hp || (pokemon.isFullHp() && (!this.healStatus || (!pokemon.status && !pokemon.getTag(BattlerTagType.CONFUSED))))) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -282,7 +279,7 @@ export class PokemonHpRestoreModifierType extends PokemonModifierType {
|
||||
|
||||
export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
||||
constructor(localeKey: string, iconImage: string, restorePercent: integer) {
|
||||
super(localeKey, iconImage, 0, restorePercent, false, (_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, 0, this.restorePercent, false, true),
|
||||
super(localeKey, iconImage, 0, restorePercent, false, (_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, 0, this.restorePercent, false, true),
|
||||
((pokemon: PlayerPokemon) => {
|
||||
if (!pokemon.isFainted()) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -305,7 +302,7 @@ export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
||||
|
||||
export class PokemonStatusHealModifierType extends PokemonModifierType {
|
||||
constructor(localeKey: string, iconImage: string) {
|
||||
super(localeKey, iconImage, ((_type, args) => new Modifiers.PokemonStatusHealModifier(this, (args[0] as PlayerPokemon).id)),
|
||||
super(localeKey, iconImage, ((_type, args) => new PokemonStatusHealModifier(this, (args[0] as PlayerPokemon).id)),
|
||||
((pokemon: PlayerPokemon) => {
|
||||
if (!pokemon.hp || (!pokemon.status && !pokemon.getTag(BattlerTagType.CONFUSED))) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -333,7 +330,7 @@ export class PokemonPpRestoreModifierType extends PokemonMoveModifierType {
|
||||
protected restorePoints: integer;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, restorePoints: integer) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints),
|
||||
super(localeKey, iconImage, (_type, args) => new PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints),
|
||||
(_pokemon: PlayerPokemon) => {
|
||||
return null;
|
||||
}, (pokemonMove: PokemonMove) => {
|
||||
@ -358,7 +355,7 @@ export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType {
|
||||
protected restorePoints: integer;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, restorePoints: integer) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints),
|
||||
super(localeKey, iconImage, (_type, args) => new PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (!pokemon.getMoveset().filter(m => m?.ppUsed).length) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -381,7 +378,7 @@ export class PokemonPpUpModifierType extends PokemonMoveModifierType {
|
||||
protected upPoints: integer;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, upPoints: integer) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints),
|
||||
super(localeKey, iconImage, (_type, args) => new PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints),
|
||||
(_pokemon: PlayerPokemon) => {
|
||||
return null;
|
||||
}, (pokemonMove: PokemonMove) => {
|
||||
@ -403,7 +400,7 @@ export class PokemonNatureChangeModifierType extends PokemonModifierType {
|
||||
protected nature: Nature;
|
||||
|
||||
constructor(nature: Nature) {
|
||||
super("", `mint_${Utils.getEnumKeys(Stat).find(s => getNatureStatMultiplier(nature, Stat[s]) > 1)?.toLowerCase() || "neutral" }`, ((_type, args) => new Modifiers.PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)),
|
||||
super("", `mint_${getEnumKeys(Stat).find(s => getNatureStatMultiplier(nature, Stat[s]) > 1)?.toLowerCase() || "neutral" }`, ((_type, args) => new PokemonNatureChangeModifier(this, (args[0] as PlayerPokemon).id, this.nature)),
|
||||
((pokemon: PlayerPokemon) => {
|
||||
if (pokemon.getNature() === this.nature) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -425,7 +422,7 @@ export class PokemonNatureChangeModifierType extends PokemonModifierType {
|
||||
|
||||
export class RememberMoveModifierType extends PokemonModifierType {
|
||||
constructor(localeKey: string, iconImage: string, group?: string) {
|
||||
super(localeKey, iconImage, (type, args) => new Modifiers.RememberMoveModifier(type, (args[0] as PlayerPokemon).id, (args[1] as integer)),
|
||||
super(localeKey, iconImage, (type, args) => new RememberMoveModifier(type, (args[0] as PlayerPokemon).id, (args[1] as integer)),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (!pokemon.getLearnableLevelMoves().length) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -439,7 +436,7 @@ export class DoubleBattleChanceBoosterModifierType extends ModifierType {
|
||||
private maxBattles: number;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, maxBattles: number) {
|
||||
super(localeKey, iconImage, (_type, _args) => new Modifiers.DoubleBattleChanceBoosterModifier(this, maxBattles), "lure");
|
||||
super(localeKey, iconImage, (_type, _args) => new DoubleBattleChanceBoosterModifier(this, maxBattles), "lure");
|
||||
|
||||
this.maxBattles = maxBattles;
|
||||
}
|
||||
@ -458,7 +455,7 @@ export class TempStatStageBoosterModifierType extends ModifierType implements Ge
|
||||
|
||||
constructor(stat: TempBattleStat) {
|
||||
const nameKey = TempStatStageBoosterModifierTypeGenerator.items[stat];
|
||||
super("", nameKey, (_type, _args) => new Modifiers.TempStatStageBoosterModifier(this, this.stat, 5));
|
||||
super("", nameKey, (_type, _args) => new TempStatStageBoosterModifier(this, this.stat, 5));
|
||||
|
||||
this.stat = stat;
|
||||
this.nameKey = nameKey;
|
||||
@ -485,7 +482,7 @@ export class BerryModifierType extends PokemonHeldItemModifierType implements Ge
|
||||
private berryType: BerryType;
|
||||
|
||||
constructor(berryType: BerryType) {
|
||||
super("", `${BerryType[berryType].toLowerCase()}_berry`, (type, args) => new Modifiers.BerryModifier(type, (args[0] as Pokemon).id, berryType), "berry");
|
||||
super("", `${BerryType[berryType].toLowerCase()}_berry`, (type, args) => new BerryModifier(type, (args[0] as Pokemon).id, berryType), "berry");
|
||||
|
||||
this.berryType = berryType;
|
||||
}
|
||||
@ -550,7 +547,7 @@ export class AttackTypeBoosterModifierType extends PokemonHeldItemModifierType i
|
||||
|
||||
constructor(moveType: Type, boostPercent: integer) {
|
||||
super("", `${getAttackTypeBoosterItemName(moveType)?.replace(/[ \-]/g, "_").toLowerCase()}`,
|
||||
(_type, args) => new Modifiers.AttackTypeBoosterModifier(this, (args[0] as Pokemon).id, moveType, boostPercent));
|
||||
(_type, args) => new AttackTypeBoosterModifier(this, (args[0] as Pokemon).id, moveType, boostPercent));
|
||||
|
||||
this.moveType = moveType;
|
||||
this.boostPercent = boostPercent;
|
||||
@ -573,7 +570,7 @@ export class AttackTypeBoosterModifierType extends PokemonHeldItemModifierType i
|
||||
export type SpeciesStatBoosterItem = keyof typeof SpeciesStatBoosterModifierTypeGenerator.items;
|
||||
|
||||
/**
|
||||
* Modifier type for {@linkcode Modifiers.SpeciesStatBoosterModifier}
|
||||
* Modifier type for {@linkcode SpeciesStatBoosterModifier}
|
||||
* @extends PokemonHeldItemModifierType
|
||||
* @implements GeneratedPersistentModifierType
|
||||
*/
|
||||
@ -582,7 +579,7 @@ export class SpeciesStatBoosterModifierType extends PokemonHeldItemModifierType
|
||||
|
||||
constructor(key: SpeciesStatBoosterItem) {
|
||||
const item = SpeciesStatBoosterModifierTypeGenerator.items[key];
|
||||
super(`modifierType:SpeciesBoosterItem.${key}`, key.toLowerCase(), (type, args) => new Modifiers.SpeciesStatBoosterModifier(type, (args[0] as Pokemon).id, item.stats, item.multiplier, item.species));
|
||||
super(`modifierType:SpeciesBoosterItem.${key}`, key.toLowerCase(), (type, args) => new SpeciesStatBoosterModifier(type, (args[0] as Pokemon).id, item.stats, item.multiplier, item.species));
|
||||
|
||||
this.key = key;
|
||||
}
|
||||
@ -594,12 +591,12 @@ export class SpeciesStatBoosterModifierType extends PokemonHeldItemModifierType
|
||||
|
||||
export class PokemonLevelIncrementModifierType extends PokemonModifierType {
|
||||
constructor(localeKey: string, iconImage: string) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id), (_pokemon: PlayerPokemon) => null);
|
||||
super(localeKey, iconImage, (_type, args) => new PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id), (_pokemon: PlayerPokemon) => null);
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
let levels = 1;
|
||||
const hasCandyJar = scene.modifiers.find(modifier => modifier instanceof Modifiers.LevelIncrementBoosterModifier);
|
||||
const hasCandyJar = scene.modifiers.find(modifier => modifier instanceof LevelIncrementBoosterModifier);
|
||||
if (hasCandyJar) {
|
||||
levels += hasCandyJar.stackCount;
|
||||
}
|
||||
@ -609,12 +606,12 @@ export class PokemonLevelIncrementModifierType extends PokemonModifierType {
|
||||
|
||||
export class AllPokemonLevelIncrementModifierType extends ModifierType {
|
||||
constructor(localeKey: string, iconImage: string) {
|
||||
super(localeKey, iconImage, (_type, _args) => new Modifiers.PokemonLevelIncrementModifier(this, -1));
|
||||
super(localeKey, iconImage, (_type, _args) => new PokemonLevelIncrementModifier(this, -1));
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
let levels = 1;
|
||||
const hasCandyJar = scene.modifiers.find(modifier => modifier instanceof Modifiers.LevelIncrementBoosterModifier);
|
||||
const hasCandyJar = scene.modifiers.find(modifier => modifier instanceof LevelIncrementBoosterModifier);
|
||||
if (hasCandyJar) {
|
||||
levels += hasCandyJar.stackCount;
|
||||
}
|
||||
@ -628,7 +625,7 @@ export class BaseStatBoosterModifierType extends PokemonHeldItemModifierType imp
|
||||
|
||||
constructor(stat: PermanentStat) {
|
||||
const key = BaseStatBoosterModifierTypeGenerator.items[stat];
|
||||
super("", key, (_type, args) => new Modifiers.BaseStatModifier(this, (args[0] as Pokemon).id, this.stat));
|
||||
super("", key, (_type, args) => new BaseStatModifier(this, (args[0] as Pokemon).id, this.stat));
|
||||
|
||||
this.stat = stat;
|
||||
this.key = key;
|
||||
@ -654,7 +651,7 @@ export class PokemonBaseStatTotalModifierType extends PokemonHeldItemModifierTyp
|
||||
private readonly statModifier: integer;
|
||||
|
||||
constructor(statModifier: integer) {
|
||||
super("modifierType:ModifierType.MYSTERY_ENCOUNTER_SHUCKLE_JUICE", "berry_juice", (_type, args) => new Modifiers.PokemonBaseStatTotalModifier(this, (args[0] as Pokemon).id, this.statModifier));
|
||||
super("modifierType:ModifierType.MYSTERY_ENCOUNTER_SHUCKLE_JUICE", "berry_juice", (_type, args) => new PokemonBaseStatTotalModifier(this, (args[0] as Pokemon).id, this.statModifier));
|
||||
this.statModifier = statModifier;
|
||||
}
|
||||
|
||||
@ -679,7 +676,7 @@ export class PokemonBaseStatFlatModifierType extends PokemonHeldItemModifierType
|
||||
private readonly stats: Stat[];
|
||||
|
||||
constructor(statModifier: integer, stats: Stat[]) {
|
||||
super("modifierType:ModifierType.MYSTERY_ENCOUNTER_OLD_GATEAU", "old_gateau", (_type, args) => new Modifiers.PokemonBaseStatFlatModifier(this, (args[0] as Pokemon).id, this.statModifier, this.stats));
|
||||
super("modifierType:ModifierType.MYSTERY_ENCOUNTER_OLD_GATEAU", "old_gateau", (_type, args) => new PokemonBaseStatFlatModifier(this, (args[0] as Pokemon).id, this.statModifier, this.stats));
|
||||
this.statModifier = statModifier;
|
||||
this.stats = stats;
|
||||
}
|
||||
@ -700,7 +697,7 @@ class AllPokemonFullHpRestoreModifierType extends ModifierType {
|
||||
private descriptionKey: string;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, descriptionKey?: string, newModifierFunc?: NewModifierFunc) {
|
||||
super(localeKey, iconImage, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false)));
|
||||
super(localeKey, iconImage, newModifierFunc || ((_type, _args) => new PokemonHpRestoreModifier(this, -1, 0, 100, false)));
|
||||
|
||||
this.descriptionKey = descriptionKey!; // TODO: is this bang correct?
|
||||
}
|
||||
@ -712,7 +709,7 @@ class AllPokemonFullHpRestoreModifierType extends ModifierType {
|
||||
|
||||
class AllPokemonFullReviveModifierType extends AllPokemonFullHpRestoreModifierType {
|
||||
constructor(localeKey: string, iconImage: string) {
|
||||
super(localeKey, iconImage, "modifierType:ModifierType.AllPokemonFullReviveModifierType", (_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false, true));
|
||||
super(localeKey, iconImage, "modifierType:ModifierType.AllPokemonFullReviveModifierType", (_type, _args) => new PokemonHpRestoreModifier(this, -1, 0, 100, false, true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -721,16 +718,16 @@ export class MoneyRewardModifierType extends ModifierType {
|
||||
private moneyMultiplierDescriptorKey: string;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, moneyMultiplier: number, moneyMultiplierDescriptorKey: string) {
|
||||
super(localeKey, iconImage, (_type, _args) => new Modifiers.MoneyRewardModifier(this, moneyMultiplier), "money", "se/buy");
|
||||
super(localeKey, iconImage, (_type, _args) => new MoneyRewardModifier(this, moneyMultiplier), "money", "se/buy");
|
||||
|
||||
this.moneyMultiplier = moneyMultiplier;
|
||||
this.moneyMultiplierDescriptorKey = moneyMultiplierDescriptorKey;
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
const moneyAmount = new Utils.IntegerHolder(scene.getWaveMoneyAmount(this.moneyMultiplier));
|
||||
const moneyAmount = new IntegerHolder(scene.getWaveMoneyAmount(this.moneyMultiplier));
|
||||
scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
|
||||
const formattedMoney = Utils.formatMoney(scene.moneyFormat, moneyAmount.value);
|
||||
const formattedMoney = formatMoney(scene.moneyFormat, moneyAmount.value);
|
||||
|
||||
return i18next.t("modifierType:ModifierType.MoneyRewardModifierType.description", {
|
||||
moneyMultiplier: i18next.t(this.moneyMultiplierDescriptorKey as any),
|
||||
@ -743,7 +740,7 @@ export class ExpBoosterModifierType extends ModifierType {
|
||||
private boostPercent: integer;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, boostPercent: integer) {
|
||||
super(localeKey, iconImage, () => new Modifiers.ExpBoosterModifier(this, boostPercent));
|
||||
super(localeKey, iconImage, () => new ExpBoosterModifier(this, boostPercent));
|
||||
|
||||
this.boostPercent = boostPercent;
|
||||
}
|
||||
@ -757,7 +754,7 @@ export class PokemonExpBoosterModifierType extends PokemonHeldItemModifierType {
|
||||
private boostPercent: integer;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, boostPercent: integer) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonExpBoosterModifier(this, (args[0] as Pokemon).id, boostPercent));
|
||||
super(localeKey, iconImage, (_type, args) => new PokemonExpBoosterModifier(this, (args[0] as Pokemon).id, boostPercent));
|
||||
|
||||
this.boostPercent = boostPercent;
|
||||
}
|
||||
@ -769,7 +766,7 @@ export class PokemonExpBoosterModifierType extends PokemonHeldItemModifierType {
|
||||
|
||||
export class PokemonFriendshipBoosterModifierType extends PokemonHeldItemModifierType {
|
||||
constructor(localeKey: string, iconImage: string) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonFriendshipBoosterModifier(this, (args[0] as Pokemon).id));
|
||||
super(localeKey, iconImage, (_type, args) => new PokemonFriendshipBoosterModifier(this, (args[0] as Pokemon).id));
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
@ -781,7 +778,7 @@ export class PokemonMoveAccuracyBoosterModifierType extends PokemonHeldItemModif
|
||||
private amount: integer;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, amount: integer, group?: string, soundName?: string) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.PokemonMoveAccuracyBoosterModifier(this, (args[0] as Pokemon).id, amount), group, soundName);
|
||||
super(localeKey, iconImage, (_type, args) => new PokemonMoveAccuracyBoosterModifier(this, (args[0] as Pokemon).id, amount), group, soundName);
|
||||
|
||||
this.amount = amount;
|
||||
}
|
||||
@ -793,7 +790,7 @@ export class PokemonMoveAccuracyBoosterModifierType extends PokemonHeldItemModif
|
||||
|
||||
export class PokemonMultiHitModifierType extends PokemonHeldItemModifierType {
|
||||
constructor(localeKey: string, iconImage: string) {
|
||||
super(localeKey, iconImage, (type, args) => new Modifiers.PokemonMultiHitModifier(type as PokemonMultiHitModifierType, (args[0] as Pokemon).id));
|
||||
super(localeKey, iconImage, (type, args) => new PokemonMultiHitModifier(type as PokemonMultiHitModifierType, (args[0] as Pokemon).id));
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
@ -805,7 +802,7 @@ export class TmModifierType extends PokemonModifierType {
|
||||
public moveId: Moves;
|
||||
|
||||
constructor(moveId: Moves) {
|
||||
super("", `tm_${Type[allMoves[moveId].type].toLowerCase()}`, (_type, args) => new Modifiers.TmModifier(this, (args[0] as PlayerPokemon).id),
|
||||
super("", `tm_${Type[allMoves[moveId].type].toLowerCase()}`, (_type, args) => new TmModifier(this, (args[0] as PlayerPokemon).id),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (pokemon.compatibleTms.indexOf(moveId) === -1 || pokemon.getMoveset().filter(m => m?.moveId === moveId).length) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -818,7 +815,7 @@ export class TmModifierType extends PokemonModifierType {
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("modifierType:ModifierType.TmModifierType.name", {
|
||||
moveId: Utils.padInt(Object.keys(tmSpecies).indexOf(this.moveId.toString()) + 1, 3),
|
||||
moveId: padInt(Object.keys(tmSpecies).indexOf(this.moveId.toString()) + 1, 3),
|
||||
moveName: allMoves[this.moveId].name,
|
||||
});
|
||||
}
|
||||
@ -832,7 +829,7 @@ export class EvolutionItemModifierType extends PokemonModifierType implements Ge
|
||||
public evolutionItem: EvolutionItem;
|
||||
|
||||
constructor(evolutionItem: EvolutionItem) {
|
||||
super("", EvolutionItem[evolutionItem].toLowerCase(), (_type, args) => new Modifiers.EvolutionItemModifier(this, (args[0] as PlayerPokemon).id),
|
||||
super("", EvolutionItem[evolutionItem].toLowerCase(), (_type, args) => new EvolutionItemModifier(this, (args[0] as PlayerPokemon).id),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId) && pokemonEvolutions[pokemon.species.speciesId].filter(e => e.item === this.evolutionItem
|
||||
&& (!e.condition || e.condition.predicate(pokemon)) && (e.preFormKey === null || e.preFormKey === pokemon.getFormKey())).length && (pokemon.getFormKey() !== SpeciesFormKey.GIGANTAMAX)) {
|
||||
@ -868,7 +865,7 @@ export class FormChangeItemModifierType extends PokemonModifierType implements G
|
||||
public formChangeItem: FormChangeItem;
|
||||
|
||||
constructor(formChangeItem: FormChangeItem) {
|
||||
super("", FormChangeItem[formChangeItem].toLowerCase(), (_type, args) => new Modifiers.PokemonFormChangeItemModifier(this, (args[0] as PlayerPokemon).id, formChangeItem, true),
|
||||
super("", FormChangeItem[formChangeItem].toLowerCase(), (_type, args) => new PokemonFormChangeItemModifier(this, (args[0] as PlayerPokemon).id, formChangeItem, true),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
// Make sure the Pokemon has alternate forms
|
||||
if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId)
|
||||
@ -902,7 +899,7 @@ export class FormChangeItemModifierType extends PokemonModifierType implements G
|
||||
|
||||
export class FusePokemonModifierType extends PokemonModifierType {
|
||||
constructor(localeKey: string, iconImage: string) {
|
||||
super(localeKey, iconImage, (_type, args) => new Modifiers.FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id),
|
||||
super(localeKey, iconImage, (_type, args) => new FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (pokemon.isFusion()) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
@ -949,7 +946,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
|
||||
let type: Type;
|
||||
|
||||
const randInt = Utils.randSeedInt(totalWeight);
|
||||
const randInt = randSeedInt(totalWeight);
|
||||
let weight = 0;
|
||||
|
||||
for (const t of attackMoveTypeWeights.keys()) {
|
||||
@ -981,7 +978,7 @@ class BaseStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
if (pregenArgs) {
|
||||
return new BaseStatBoosterModifierType(pregenArgs[0]);
|
||||
}
|
||||
const randStat: PermanentStat = Utils.randSeedInt(Stat.SPD + 1);
|
||||
const randStat: PermanentStat = randSeedInt(Stat.SPD + 1);
|
||||
return new BaseStatBoosterModifierType(randStat);
|
||||
});
|
||||
}
|
||||
@ -1002,7 +999,7 @@ class TempStatStageBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && TEMP_BATTLE_STATS.includes(pregenArgs[0])) {
|
||||
return new TempStatStageBoosterModifierType(pregenArgs[0]);
|
||||
}
|
||||
const randStat: TempBattleStat = Utils.randSeedInt(Stat.ACC, Stat.ATK);
|
||||
const randStat: TempBattleStat = randSeedInt(Stat.ACC, Stat.ATK);
|
||||
return new TempStatStageBoosterModifierType(randStat);
|
||||
});
|
||||
}
|
||||
@ -1044,8 +1041,8 @@ class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
const checkedStats = values[i].stats;
|
||||
|
||||
// If party member already has the item being weighted currently, skip to the next item
|
||||
const hasItem = p.getHeldItems().some(m => m instanceof Modifiers.SpeciesStatBoosterModifier
|
||||
&& (m as Modifiers.SpeciesStatBoosterModifier).contains(checkedSpecies[0], checkedStats[0]));
|
||||
const hasItem = p.getHeldItems().some(m => m instanceof SpeciesStatBoosterModifier
|
||||
&& (m as SpeciesStatBoosterModifier).contains(checkedSpecies[0], checkedStats[0]));
|
||||
|
||||
if (!hasItem) {
|
||||
if (checkedSpecies.includes(speciesId) || (!!fusionSpeciesId && checkedSpecies.includes(fusionSpeciesId))) {
|
||||
@ -1065,7 +1062,7 @@ class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
}
|
||||
|
||||
if (totalWeight !== 0) {
|
||||
const randInt = Utils.randSeedInt(totalWeight, 1);
|
||||
const randInt = randSeedInt(totalWeight, 1);
|
||||
let weight = 0;
|
||||
|
||||
for (const i in weights) {
|
||||
@ -1095,7 +1092,7 @@ class TmModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
if (!tierUniqueCompatibleTms.length) {
|
||||
return null;
|
||||
}
|
||||
const randTmIndex = Utils.randSeedInt(tierUniqueCompatibleTms.length);
|
||||
const randTmIndex = randSeedInt(tierUniqueCompatibleTms.length);
|
||||
return new TmModifierType(tierUniqueCompatibleTms[randTmIndex]);
|
||||
});
|
||||
}
|
||||
@ -1123,7 +1120,7 @@ class EvolutionItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new EvolutionItemModifierType(evolutionItemPool[Utils.randSeedInt(evolutionItemPool.length)]!); // TODO: is the bang correct?
|
||||
return new EvolutionItemModifierType(evolutionItemPool[randSeedInt(evolutionItemPool.length)]!); // TODO: is the bang correct?
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1137,12 +1134,12 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
|
||||
const formChangeItemPool = [...new Set(party.filter(p => pokemonFormChanges.hasOwnProperty(p.species.speciesId)).map(p => {
|
||||
const formChanges = pokemonFormChanges[p.species.speciesId];
|
||||
let formChangeItemTriggers = formChanges.filter(fc => ((fc.formKey.indexOf(SpeciesFormKey.MEGA) === -1 && fc.formKey.indexOf(SpeciesFormKey.PRIMAL) === -1) || party[0].scene.getModifiers(Modifiers.MegaEvolutionAccessModifier).length)
|
||||
&& ((fc.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) === -1 && fc.formKey.indexOf(SpeciesFormKey.ETERNAMAX) === -1) || party[0].scene.getModifiers(Modifiers.GigantamaxAccessModifier).length)
|
||||
let formChangeItemTriggers = formChanges.filter(fc => ((fc.formKey.indexOf(SpeciesFormKey.MEGA) === -1 && fc.formKey.indexOf(SpeciesFormKey.PRIMAL) === -1) || party[0].scene.getModifiers(MegaEvolutionAccessModifier).length)
|
||||
&& ((fc.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) === -1 && fc.formKey.indexOf(SpeciesFormKey.ETERNAMAX) === -1) || party[0].scene.getModifiers(GigantamaxAccessModifier).length)
|
||||
&& (!fc.conditions.length || fc.conditions.filter(cond => cond instanceof SpeciesFormChangeCondition && cond.predicate(p)).length)
|
||||
&& (fc.preFormKey === p.getFormKey()))
|
||||
.map(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)
|
||||
.filter(t => t && t.active && !p.scene.findModifier(m => m instanceof Modifiers.PokemonFormChangeItemModifier && m.pokemonId === p.id && m.formChangeItem === t.item));
|
||||
.filter(t => t && t.active && !p.scene.findModifier(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === p.id && m.formChangeItem === t.item));
|
||||
|
||||
if (p.species.speciesId === Species.NECROZMA) {
|
||||
// technically we could use a simplified version and check for formChanges.length > 3, but in case any code changes later, this might break...
|
||||
@ -1177,7 +1174,7 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new FormChangeItemModifierType(formChangeItemPool[Utils.randSeedInt(formChangeItemPool.length)]);
|
||||
return new FormChangeItemModifierType(formChangeItemPool[randSeedInt(formChangeItemPool.length)]);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1186,7 +1183,7 @@ export class TerastallizeModifierType extends PokemonHeldItemModifierType implem
|
||||
private teraType: Type;
|
||||
|
||||
constructor(teraType: Type) {
|
||||
super("", `${Type[teraType].toLowerCase()}_tera_shard`, (type, args) => new Modifiers.TerastallizeModifier(type as TerastallizeModifierType, (args[0] as Pokemon).id, teraType), "tera_shard");
|
||||
super("", `${Type[teraType].toLowerCase()}_tera_shard`, (type, args) => new TerastallizeModifier(type as TerastallizeModifierType, (args[0] as Pokemon).id, teraType), "tera_shard");
|
||||
|
||||
this.teraType = teraType;
|
||||
}
|
||||
@ -1208,7 +1205,7 @@ export class ContactHeldItemTransferChanceModifierType extends PokemonHeldItemMo
|
||||
private chancePercent: integer;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, chancePercent: integer, group?: string, soundName?: string) {
|
||||
super(localeKey, iconImage, (type, args) => new Modifiers.ContactHeldItemTransferChanceModifier(type, (args[0] as Pokemon).id, chancePercent), group, soundName);
|
||||
super(localeKey, iconImage, (type, args) => new ContactHeldItemTransferChanceModifier(type, (args[0] as Pokemon).id, chancePercent), group, soundName);
|
||||
|
||||
this.chancePercent = chancePercent;
|
||||
}
|
||||
@ -1220,7 +1217,7 @@ export class ContactHeldItemTransferChanceModifierType extends PokemonHeldItemMo
|
||||
|
||||
export class TurnHeldItemTransferModifierType extends PokemonHeldItemModifierType {
|
||||
constructor(localeKey: string, iconImage: string, group?: string, soundName?: string) {
|
||||
super(localeKey, iconImage, (type, args) => new Modifiers.TurnHeldItemTransferModifier(type, (args[0] as Pokemon).id), group, soundName);
|
||||
super(localeKey, iconImage, (type, args) => new TurnHeldItemTransferModifier(type, (args[0] as Pokemon).id), group, soundName);
|
||||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
@ -1233,7 +1230,7 @@ export class EnemyAttackStatusEffectChanceModifierType extends ModifierType {
|
||||
private effect: StatusEffect;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, chancePercent: integer, effect: StatusEffect, stackCount?: integer) {
|
||||
super(localeKey, iconImage, (type, args) => new Modifiers.EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent, stackCount), "enemy_status_chance");
|
||||
super(localeKey, iconImage, (type, args) => new EnemyAttackStatusEffectChanceModifier(type, effect, chancePercent, stackCount), "enemy_status_chance");
|
||||
|
||||
this.chancePercent = chancePercent;
|
||||
this.effect = effect;
|
||||
@ -1251,7 +1248,7 @@ export class EnemyEndureChanceModifierType extends ModifierType {
|
||||
private chancePercent: number;
|
||||
|
||||
constructor(localeKey: string, iconImage: string, chancePercent: number) {
|
||||
super(localeKey, iconImage, (type, _args) => new Modifiers.EnemyEndureChanceModifier(type, chancePercent), "enemy_endure");
|
||||
super(localeKey, iconImage, (type, _args) => new EnemyEndureChanceModifier(type, chancePercent), "enemy_endure");
|
||||
|
||||
this.chancePercent = chancePercent;
|
||||
}
|
||||
@ -1298,7 +1295,7 @@ function skipInLastClassicWaveOrDefault(defaultWeight: integer) : WeightedModifi
|
||||
*/
|
||||
function lureWeightFunc(maxBattles: number, weight: number): WeightedModifierTypeWeightFunc {
|
||||
return (party: Pokemon[]) => {
|
||||
const lures = party[0].scene.getModifiers(Modifiers.DoubleBattleChanceBoosterModifier);
|
||||
const lures = party[0].scene.getModifiers(DoubleBattleChanceBoosterModifier);
|
||||
return !(party[0].scene.gameMode.isClassic && party[0].scene.currentBattle.waveIndex === 199) && (lures.length === 0 || lures.filter(m => m.getMaxBattles() === maxBattles && m.getBattleCount() >= maxBattles * 0.6).length === 0) ? weight : 0;
|
||||
};
|
||||
}
|
||||
@ -1388,13 +1385,13 @@ export const modifierTypes = {
|
||||
RARE_FORM_CHANGE_ITEM: () => new FormChangeItemModifierTypeGenerator(true),
|
||||
|
||||
EVOLUTION_TRACKER_GIMMIGHOUL: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVOLUTION_TRACKER_GIMMIGHOUL", "relic_gold",
|
||||
(type, args) => new Modifiers.EvoTrackerModifier(type, (args[0] as Pokemon).id, Species.GIMMIGHOUL, 10)),
|
||||
(type, args) => new EvoTrackerModifier(type, (args[0] as Pokemon).id, Species.GIMMIGHOUL, 10)),
|
||||
|
||||
MEGA_BRACELET: () => new ModifierType("modifierType:ModifierType.MEGA_BRACELET", "mega_bracelet", (type, _args) => new Modifiers.MegaEvolutionAccessModifier(type)),
|
||||
DYNAMAX_BAND: () => new ModifierType("modifierType:ModifierType.DYNAMAX_BAND", "dynamax_band", (type, _args) => new Modifiers.GigantamaxAccessModifier(type)),
|
||||
TERA_ORB: () => new ModifierType("modifierType:ModifierType.TERA_ORB", "tera_orb", (type, _args) => new Modifiers.TerastallizeAccessModifier(type)),
|
||||
MEGA_BRACELET: () => new ModifierType("modifierType:ModifierType.MEGA_BRACELET", "mega_bracelet", (type, _args) => new MegaEvolutionAccessModifier(type)),
|
||||
DYNAMAX_BAND: () => new ModifierType("modifierType:ModifierType.DYNAMAX_BAND", "dynamax_band", (type, _args) => new GigantamaxAccessModifier(type)),
|
||||
TERA_ORB: () => new ModifierType("modifierType:ModifierType.TERA_ORB", "tera_orb", (type, _args) => new TerastallizeAccessModifier(type)),
|
||||
|
||||
MAP: () => new ModifierType("modifierType:ModifierType.MAP", "map", (type, _args) => new Modifiers.MapModifier(type)),
|
||||
MAP: () => new ModifierType("modifierType:ModifierType.MAP", "map", (type, _args) => new MapModifier(type)),
|
||||
|
||||
POTION: () => new PokemonHpRestoreModifierType("modifierType:ModifierType.POTION", "potion", 20, 10),
|
||||
SUPER_POTION: () => new PokemonHpRestoreModifierType("modifierType:ModifierType.SUPER_POTION", "super_potion", 50, 25),
|
||||
@ -1409,8 +1406,8 @@ export const modifierTypes = {
|
||||
|
||||
SACRED_ASH: () => new AllPokemonFullReviveModifierType("modifierType:ModifierType.SACRED_ASH", "sacred_ash"),
|
||||
|
||||
REVIVER_SEED: () => new PokemonHeldItemModifierType("modifierType:ModifierType.REVIVER_SEED", "reviver_seed", (type, args) => new Modifiers.PokemonInstantReviveModifier(type, (args[0] as Pokemon).id)),
|
||||
WHITE_HERB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.WHITE_HERB", "white_herb", (type, args) => new Modifiers.ResetNegativeStatStageModifier(type, (args[0] as Pokemon).id)),
|
||||
REVIVER_SEED: () => new PokemonHeldItemModifierType("modifierType:ModifierType.REVIVER_SEED", "reviver_seed", (type, args) => new PokemonInstantReviveModifier(type, (args[0] as Pokemon).id)),
|
||||
WHITE_HERB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.WHITE_HERB", "white_herb", (type, args) => new ResetNegativeStatStageModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
ETHER: () => new PokemonPpRestoreModifierType("modifierType:ModifierType.ETHER", "ether", 10),
|
||||
MAX_ETHER: () => new PokemonPpRestoreModifierType("modifierType:ModifierType.MAX_ETHER", "max_ether", -1),
|
||||
@ -1440,7 +1437,7 @@ export const modifierTypes = {
|
||||
amount: i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.extra.stage")
|
||||
});
|
||||
}
|
||||
}("modifierType:ModifierType.DIRE_HIT", "dire_hit", (type, _args) => new Modifiers.TempCritBoosterModifier(type, 5)),
|
||||
}("modifierType:ModifierType.DIRE_HIT", "dire_hit", (type, _args) => new TempCritBoosterModifier(type, 5)),
|
||||
|
||||
BASE_STAT_BOOSTER: () => new BaseStatBoosterModifierTypeGenerator(),
|
||||
|
||||
@ -1450,22 +1447,22 @@ export const modifierTypes = {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in Nature)) {
|
||||
return new PokemonNatureChangeModifierType(pregenArgs[0] as Nature);
|
||||
}
|
||||
return new PokemonNatureChangeModifierType(Utils.randSeedInt(Utils.getEnumValues(Nature).length) as Nature);
|
||||
return new PokemonNatureChangeModifierType(randSeedInt(getEnumValues(Nature).length) as Nature);
|
||||
}),
|
||||
|
||||
TERA_SHARD: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in Type)) {
|
||||
return new TerastallizeModifierType(pregenArgs[0] as Type);
|
||||
}
|
||||
if (!party[0].scene.getModifiers(Modifiers.TerastallizeAccessModifier).length) {
|
||||
if (!party[0].scene.getModifiers(TerastallizeAccessModifier).length) {
|
||||
return null;
|
||||
}
|
||||
let type: Type;
|
||||
if (!Utils.randSeedInt(3)) {
|
||||
if (!randSeedInt(3)) {
|
||||
const partyMemberTypes = party.map(p => p.getTypes(false, false, true)).flat();
|
||||
type = Utils.randSeedItem(partyMemberTypes);
|
||||
type = randSeedItem(partyMemberTypes);
|
||||
} else {
|
||||
type = Utils.randSeedInt(64) ? Utils.randSeedInt(18) as Type : Type.STELLAR;
|
||||
type = randSeedInt(64) ? randSeedInt(18) as Type : Type.STELLAR;
|
||||
}
|
||||
return new TerastallizeModifierType(type);
|
||||
}),
|
||||
@ -1474,9 +1471,9 @@ export const modifierTypes = {
|
||||
if (pregenArgs && (pregenArgs.length === 1) && (pregenArgs[0] in BerryType)) {
|
||||
return new BerryModifierType(pregenArgs[0] as BerryType);
|
||||
}
|
||||
const berryTypes = Utils.getEnumValues(BerryType);
|
||||
const berryTypes = getEnumValues(BerryType);
|
||||
let randBerryType: BerryType;
|
||||
const rand = Utils.randSeedInt(12);
|
||||
const rand = randSeedInt(12);
|
||||
if (rand < 2) {
|
||||
randBerryType = BerryType.SITRUS;
|
||||
} else if (rand < 4) {
|
||||
@ -1484,7 +1481,7 @@ export const modifierTypes = {
|
||||
} else if (rand < 6) {
|
||||
randBerryType = BerryType.LEPPA;
|
||||
} else {
|
||||
randBerryType = berryTypes[Utils.randSeedInt(berryTypes.length - 3) + 2];
|
||||
randBerryType = berryTypes[randSeedInt(berryTypes.length - 3) + 2];
|
||||
}
|
||||
return new BerryModifierType(randBerryType);
|
||||
}),
|
||||
@ -1495,10 +1492,10 @@ export const modifierTypes = {
|
||||
|
||||
MEMORY_MUSHROOM: () => new RememberMoveModifierType("modifierType:ModifierType.MEMORY_MUSHROOM", "big_mushroom"),
|
||||
|
||||
EXP_SHARE: () => new ModifierType("modifierType:ModifierType.EXP_SHARE", "exp_share", (type, _args) => new Modifiers.ExpShareModifier(type)),
|
||||
EXP_BALANCE: () => new ModifierType("modifierType:ModifierType.EXP_BALANCE", "exp_balance", (type, _args) => new Modifiers.ExpBalanceModifier(type)),
|
||||
EXP_SHARE: () => new ModifierType("modifierType:ModifierType.EXP_SHARE", "exp_share", (type, _args) => new ExpShareModifier(type)),
|
||||
EXP_BALANCE: () => new ModifierType("modifierType:ModifierType.EXP_BALANCE", "exp_balance", (type, _args) => new ExpBalanceModifier(type)),
|
||||
|
||||
OVAL_CHARM: () => new ModifierType("modifierType:ModifierType.OVAL_CHARM", "oval_charm", (type, _args) => new Modifiers.MultipleParticipantExpBonusModifier(type)),
|
||||
OVAL_CHARM: () => new ModifierType("modifierType:ModifierType.OVAL_CHARM", "oval_charm", (type, _args) => new MultipleParticipantExpBonusModifier(type)),
|
||||
|
||||
EXP_CHARM: () => new ExpBoosterModifierType("modifierType:ModifierType.EXP_CHARM", "exp_charm", 25),
|
||||
SUPER_EXP_CHARM: () => new ExpBoosterModifierType("modifierType:ModifierType.SUPER_EXP_CHARM", "super_exp_charm", 60),
|
||||
@ -1509,51 +1506,51 @@ export const modifierTypes = {
|
||||
|
||||
SOOTHE_BELL: () => new PokemonFriendshipBoosterModifierType("modifierType:ModifierType.SOOTHE_BELL", "soothe_bell"),
|
||||
|
||||
SCOPE_LENS: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SCOPE_LENS", "scope_lens", (type, args) => new Modifiers.CritBoosterModifier(type, (args[0] as Pokemon).id, 1)),
|
||||
LEEK: () => new PokemonHeldItemModifierType("modifierType:ModifierType.LEEK", "leek", (type, args) => new Modifiers.SpeciesCritBoosterModifier(type, (args[0] as Pokemon).id, 2, [Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD])),
|
||||
SCOPE_LENS: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SCOPE_LENS", "scope_lens", (type, args) => new CritBoosterModifier(type, (args[0] as Pokemon).id, 1)),
|
||||
LEEK: () => new PokemonHeldItemModifierType("modifierType:ModifierType.LEEK", "leek", (type, args) => new SpeciesCritBoosterModifier(type, (args[0] as Pokemon).id, 2, [Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD])),
|
||||
|
||||
EVIOLITE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVIOLITE", "eviolite", (type, args) => new Modifiers.EvolutionStatBoosterModifier(type, (args[0] as Pokemon).id, [Stat.DEF, Stat.SPDEF], 1.5)),
|
||||
EVIOLITE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVIOLITE", "eviolite", (type, args) => new EvolutionStatBoosterModifier(type, (args[0] as Pokemon).id, [Stat.DEF, Stat.SPDEF], 1.5)),
|
||||
|
||||
SOUL_DEW: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SOUL_DEW", "soul_dew", (type, args) => new Modifiers.PokemonNatureWeightModifier(type, (args[0] as Pokemon).id)),
|
||||
SOUL_DEW: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SOUL_DEW", "soul_dew", (type, args) => new PokemonNatureWeightModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
NUGGET: () => new MoneyRewardModifierType("modifierType:ModifierType.NUGGET", "nugget", 1, "modifierType:ModifierType.MoneyRewardModifierType.extra.small"),
|
||||
BIG_NUGGET: () => new MoneyRewardModifierType("modifierType:ModifierType.BIG_NUGGET", "big_nugget", 2.5, "modifierType:ModifierType.MoneyRewardModifierType.extra.moderate"),
|
||||
RELIC_GOLD: () => new MoneyRewardModifierType("modifierType:ModifierType.RELIC_GOLD", "relic_gold", 10, "modifierType:ModifierType.MoneyRewardModifierType.extra.large"),
|
||||
|
||||
AMULET_COIN: () => new ModifierType("modifierType:ModifierType.AMULET_COIN", "amulet_coin", (type, _args) => new Modifiers.MoneyMultiplierModifier(type)),
|
||||
GOLDEN_PUNCH: () => new PokemonHeldItemModifierType("modifierType:ModifierType.GOLDEN_PUNCH", "golden_punch", (type, args) => new Modifiers.DamageMoneyRewardModifier(type, (args[0] as Pokemon).id)),
|
||||
COIN_CASE: () => new ModifierType("modifierType:ModifierType.COIN_CASE", "coin_case", (type, _args) => new Modifiers.MoneyInterestModifier(type)),
|
||||
AMULET_COIN: () => new ModifierType("modifierType:ModifierType.AMULET_COIN", "amulet_coin", (type, _args) => new MoneyMultiplierModifier(type)),
|
||||
GOLDEN_PUNCH: () => new PokemonHeldItemModifierType("modifierType:ModifierType.GOLDEN_PUNCH", "golden_punch", (type, args) => new DamageMoneyRewardModifier(type, (args[0] as Pokemon).id)),
|
||||
COIN_CASE: () => new ModifierType("modifierType:ModifierType.COIN_CASE", "coin_case", (type, _args) => new MoneyInterestModifier(type)),
|
||||
|
||||
LOCK_CAPSULE: () => new ModifierType("modifierType:ModifierType.LOCK_CAPSULE", "lock_capsule", (type, _args) => new Modifiers.LockModifierTiersModifier(type)),
|
||||
LOCK_CAPSULE: () => new ModifierType("modifierType:ModifierType.LOCK_CAPSULE", "lock_capsule", (type, _args) => new LockModifierTiersModifier(type)),
|
||||
|
||||
GRIP_CLAW: () => new ContactHeldItemTransferChanceModifierType("modifierType:ModifierType.GRIP_CLAW", "grip_claw", 10),
|
||||
WIDE_LENS: () => new PokemonMoveAccuracyBoosterModifierType("modifierType:ModifierType.WIDE_LENS", "wide_lens", 5),
|
||||
|
||||
MULTI_LENS: () => new PokemonMultiHitModifierType("modifierType:ModifierType.MULTI_LENS", "zoom_lens"),
|
||||
|
||||
HEALING_CHARM: () => new ModifierType("modifierType:ModifierType.HEALING_CHARM", "healing_charm", (type, _args) => new Modifiers.HealingBoosterModifier(type, 1.1)),
|
||||
CANDY_JAR: () => new ModifierType("modifierType:ModifierType.CANDY_JAR", "candy_jar", (type, _args) => new Modifiers.LevelIncrementBoosterModifier(type)),
|
||||
HEALING_CHARM: () => new ModifierType("modifierType:ModifierType.HEALING_CHARM", "healing_charm", (type, _args) => new HealingBoosterModifier(type, 1.1)),
|
||||
CANDY_JAR: () => new ModifierType("modifierType:ModifierType.CANDY_JAR", "candy_jar", (type, _args) => new LevelIncrementBoosterModifier(type)),
|
||||
|
||||
BERRY_POUCH: () => new ModifierType("modifierType:ModifierType.BERRY_POUCH", "berry_pouch", (type, _args) => new Modifiers.PreserveBerryModifier(type)),
|
||||
BERRY_POUCH: () => new ModifierType("modifierType:ModifierType.BERRY_POUCH", "berry_pouch", (type, _args) => new PreserveBerryModifier(type)),
|
||||
|
||||
FOCUS_BAND: () => new PokemonHeldItemModifierType("modifierType:ModifierType.FOCUS_BAND", "focus_band", (type, args) => new Modifiers.SurviveDamageModifier(type, (args[0] as Pokemon).id)),
|
||||
FOCUS_BAND: () => new PokemonHeldItemModifierType("modifierType:ModifierType.FOCUS_BAND", "focus_band", (type, args) => new SurviveDamageModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
QUICK_CLAW: () => new PokemonHeldItemModifierType("modifierType:ModifierType.QUICK_CLAW", "quick_claw", (type, args) => new Modifiers.BypassSpeedChanceModifier(type, (args[0] as Pokemon).id)),
|
||||
QUICK_CLAW: () => new PokemonHeldItemModifierType("modifierType:ModifierType.QUICK_CLAW", "quick_claw", (type, args) => new BypassSpeedChanceModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
KINGS_ROCK: () => new PokemonHeldItemModifierType("modifierType:ModifierType.KINGS_ROCK", "kings_rock", (type, args) => new Modifiers.FlinchChanceModifier(type, (args[0] as Pokemon).id)),
|
||||
KINGS_ROCK: () => new PokemonHeldItemModifierType("modifierType:ModifierType.KINGS_ROCK", "kings_rock", (type, args) => new FlinchChanceModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
LEFTOVERS: () => new PokemonHeldItemModifierType("modifierType:ModifierType.LEFTOVERS", "leftovers", (type, args) => new Modifiers.TurnHealModifier(type, (args[0] as Pokemon).id)),
|
||||
SHELL_BELL: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SHELL_BELL", "shell_bell", (type, args) => new Modifiers.HitHealModifier(type, (args[0] as Pokemon).id)),
|
||||
LEFTOVERS: () => new PokemonHeldItemModifierType("modifierType:ModifierType.LEFTOVERS", "leftovers", (type, args) => new TurnHealModifier(type, (args[0] as Pokemon).id)),
|
||||
SHELL_BELL: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SHELL_BELL", "shell_bell", (type, args) => new HitHealModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
TOXIC_ORB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.TOXIC_ORB", "toxic_orb", (type, args) => new Modifiers.TurnStatusEffectModifier(type, (args[0] as Pokemon).id)),
|
||||
FLAME_ORB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.FLAME_ORB", "flame_orb", (type, args) => new Modifiers.TurnStatusEffectModifier(type, (args[0] as Pokemon).id)),
|
||||
TOXIC_ORB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.TOXIC_ORB", "toxic_orb", (type, args) => new TurnStatusEffectModifier(type, (args[0] as Pokemon).id)),
|
||||
FLAME_ORB: () => new PokemonHeldItemModifierType("modifierType:ModifierType.FLAME_ORB", "flame_orb", (type, args) => new TurnStatusEffectModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
BATON: () => new PokemonHeldItemModifierType("modifierType:ModifierType.BATON", "baton", (type, args) => new Modifiers.SwitchEffectTransferModifier(type, (args[0] as Pokemon).id)),
|
||||
BATON: () => new PokemonHeldItemModifierType("modifierType:ModifierType.BATON", "baton", (type, args) => new SwitchEffectTransferModifier(type, (args[0] as Pokemon).id)),
|
||||
|
||||
SHINY_CHARM: () => new ModifierType("modifierType:ModifierType.SHINY_CHARM", "shiny_charm", (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)),
|
||||
ABILITY_CHARM: () => new ModifierType("modifierType:ModifierType.ABILITY_CHARM", "ability_charm", (type, _args) => new Modifiers.HiddenAbilityRateBoosterModifier(type)),
|
||||
SHINY_CHARM: () => new ModifierType("modifierType:ModifierType.SHINY_CHARM", "shiny_charm", (type, _args) => new ShinyRateBoosterModifier(type)),
|
||||
ABILITY_CHARM: () => new ModifierType("modifierType:ModifierType.ABILITY_CHARM", "ability_charm", (type, _args) => new HiddenAbilityRateBoosterModifier(type)),
|
||||
|
||||
IV_SCANNER: () => new ModifierType("modifierType:ModifierType.IV_SCANNER", "scanner", (type, _args) => new Modifiers.IvScannerModifier(type)),
|
||||
IV_SCANNER: () => new ModifierType("modifierType:ModifierType.IV_SCANNER", "scanner", (type, _args) => new IvScannerModifier(type)),
|
||||
|
||||
DNA_SPLICERS: () => new FusePokemonModifierType("modifierType:ModifierType.DNA_SPLICERS", "dna_splicers"),
|
||||
|
||||
@ -1563,40 +1560,40 @@ export const modifierTypes = {
|
||||
VOUCHER_PLUS: () => new AddVoucherModifierType(VoucherType.PLUS, 1),
|
||||
VOUCHER_PREMIUM: () => new AddVoucherModifierType(VoucherType.PREMIUM, 1),
|
||||
|
||||
GOLDEN_POKEBALL: () => new ModifierType("modifierType:ModifierType.GOLDEN_POKEBALL", "pb_gold", (type, _args) => new Modifiers.ExtraModifierModifier(type), undefined, "se/pb_bounce_1"),
|
||||
SILVER_POKEBALL: () => new ModifierType("modifierType:ModifierType.SILVER_POKEBALL", "pb_silver", (type, _args) => new Modifiers.TempExtraModifierModifier(type, 100), undefined, "se/pb_bounce_1"),
|
||||
GOLDEN_POKEBALL: () => new ModifierType("modifierType:ModifierType.GOLDEN_POKEBALL", "pb_gold", (type, _args) => new ExtraModifierModifier(type), undefined, "se/pb_bounce_1"),
|
||||
SILVER_POKEBALL: () => new ModifierType("modifierType:ModifierType.SILVER_POKEBALL", "pb_silver", (type, _args) => new TempExtraModifierModifier(type), undefined, "se/pb_bounce_1"),
|
||||
|
||||
ENEMY_DAMAGE_BOOSTER: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_BOOSTER", "wl_item_drop", (type, _args) => new Modifiers.EnemyDamageBoosterModifier(type, 5)),
|
||||
ENEMY_DAMAGE_REDUCTION: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_REDUCTION", "wl_guard_spec", (type, _args) => new Modifiers.EnemyDamageReducerModifier(type, 2.5)),
|
||||
//ENEMY_SUPER_EFFECT_BOOSTER: () => new ModifierType('Type Advantage Token', 'Increases damage of super effective attacks by 30%', (type, _args) => new Modifiers.EnemySuperEffectiveDamageBoosterModifier(type, 30), 'wl_custom_super_effective'),
|
||||
ENEMY_HEAL: () => new ModifierType("modifierType:ModifierType.ENEMY_HEAL", "wl_potion", (type, _args) => new Modifiers.EnemyTurnHealModifier(type, 2, 10)),
|
||||
ENEMY_DAMAGE_BOOSTER: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_BOOSTER", "wl_item_drop", (type, _args) => new EnemyDamageBoosterModifier(type, 5)),
|
||||
ENEMY_DAMAGE_REDUCTION: () => new ModifierType("modifierType:ModifierType.ENEMY_DAMAGE_REDUCTION", "wl_guard_spec", (type, _args) => new EnemyDamageReducerModifier(type, 2.5)),
|
||||
//ENEMY_SUPER_EFFECT_BOOSTER: () => new ModifierType('Type Advantage Token', 'Increases damage of super effective attacks by 30%', (type, _args) => new EnemySuperEffectiveDamageBoosterModifier(type, 30), 'wl_custom_super_effective'),
|
||||
ENEMY_HEAL: () => new ModifierType("modifierType:ModifierType.ENEMY_HEAL", "wl_potion", (type, _args) => new EnemyTurnHealModifier(type, 2, 10)),
|
||||
ENEMY_ATTACK_POISON_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_POISON_CHANCE", "wl_antidote", 5, StatusEffect.POISON, 10),
|
||||
ENEMY_ATTACK_PARALYZE_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_PARALYZE_CHANCE", "wl_paralyze_heal", 2.5, StatusEffect.PARALYSIS, 10),
|
||||
ENEMY_ATTACK_BURN_CHANCE: () => new EnemyAttackStatusEffectChanceModifierType("modifierType:ModifierType.ENEMY_ATTACK_BURN_CHANCE", "wl_burn_heal", 5, StatusEffect.BURN, 10),
|
||||
ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE", "wl_full_heal", (type, _args) => new Modifiers.EnemyStatusEffectHealChanceModifier(type, 2.5, 10)),
|
||||
ENEMY_STATUS_EFFECT_HEAL_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_STATUS_EFFECT_HEAL_CHANCE", "wl_full_heal", (type, _args) => new EnemyStatusEffectHealChanceModifier(type, 2.5, 10)),
|
||||
ENEMY_ENDURE_CHANCE: () => new EnemyEndureChanceModifierType("modifierType:ModifierType.ENEMY_ENDURE_CHANCE", "wl_reset_urge", 2),
|
||||
ENEMY_FUSED_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_FUSED_CHANCE", "wl_custom_spliced", (type, _args) => new Modifiers.EnemyFusionChanceModifier(type, 1)),
|
||||
ENEMY_FUSED_CHANCE: () => new ModifierType("modifierType:ModifierType.ENEMY_FUSED_CHANCE", "wl_custom_spliced", (type, _args) => new EnemyFusionChanceModifier(type, 1)),
|
||||
|
||||
MYSTERY_ENCOUNTER_SHUCKLE_JUICE: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs) {
|
||||
return new PokemonBaseStatTotalModifierType(pregenArgs[0] as number);
|
||||
}
|
||||
return new PokemonBaseStatTotalModifierType(Utils.randSeedInt(20));
|
||||
return new PokemonBaseStatTotalModifierType(randSeedInt(20));
|
||||
}),
|
||||
MYSTERY_ENCOUNTER_OLD_GATEAU: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs) {
|
||||
return new PokemonBaseStatFlatModifierType(pregenArgs[0] as number, pregenArgs[1] as Stat[]);
|
||||
}
|
||||
return new PokemonBaseStatFlatModifierType(Utils.randSeedInt(20), [Stat.HP, Stat.ATK, Stat.DEF]);
|
||||
return new PokemonBaseStatFlatModifierType(randSeedInt(20), [Stat.HP, Stat.ATK, Stat.DEF]);
|
||||
}),
|
||||
MYSTERY_ENCOUNTER_BLACK_SLUDGE: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => {
|
||||
if (pregenArgs) {
|
||||
return new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_BLACK_SLUDGE", "black_sludge", (type, _args) => new Modifiers.HealShopCostModifier(type, pregenArgs[0] as number));
|
||||
return new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_BLACK_SLUDGE", "black_sludge", (type, _args) => new HealShopCostModifier(type, pregenArgs[0] as number));
|
||||
}
|
||||
return new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_BLACK_SLUDGE", "black_sludge", (type, _args) => new Modifiers.HealShopCostModifier(type, 2.5));
|
||||
return new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_BLACK_SLUDGE", "black_sludge", (type, _args) => new HealShopCostModifier(type, 2.5));
|
||||
}),
|
||||
MYSTERY_ENCOUNTER_MACHO_BRACE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_MACHO_BRACE", "macho_brace", (type, args) => new Modifiers.PokemonIncrementingStatModifier(type, (args[0] as Pokemon).id)),
|
||||
MYSTERY_ENCOUNTER_GOLDEN_BUG_NET: () => new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET", "golden_net", (type, _args) => new Modifiers.BoostBugSpawnModifier(type)),
|
||||
MYSTERY_ENCOUNTER_MACHO_BRACE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_MACHO_BRACE", "macho_brace", (type, args) => new PokemonIncrementingStatModifier(type, (args[0] as Pokemon).id)),
|
||||
MYSTERY_ENCOUNTER_GOLDEN_BUG_NET: () => new ModifierType("modifierType:ModifierType.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET", "golden_net", (type, _args) => new BoostBugSpawnModifier(type)),
|
||||
};
|
||||
|
||||
interface ModifierPool {
|
||||
@ -1645,8 +1642,8 @@ const modifierPool: ModifierPool = {
|
||||
new WeightedModifierType(modifierTypes.PP_UP, 2),
|
||||
new WeightedModifierType(modifierTypes.FULL_HEAL, (party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status && !p.getHeldItems().some(i => {
|
||||
if (i instanceof Modifiers.TurnStatusEffectModifier) {
|
||||
return (i as Modifiers.TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
if (i instanceof TurnStatusEffectModifier) {
|
||||
return (i as TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
}
|
||||
return false;
|
||||
})).length, 3);
|
||||
@ -1673,8 +1670,8 @@ const modifierPool: ModifierPool = {
|
||||
}, 3),
|
||||
new WeightedModifierType(modifierTypes.FULL_RESTORE, (party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status && !p.getHeldItems().some(i => {
|
||||
if (i instanceof Modifiers.TurnStatusEffectModifier) {
|
||||
return (i as Modifiers.TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
if (i instanceof TurnStatusEffectModifier) {
|
||||
return (i as TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
}
|
||||
return false;
|
||||
})).length, 3);
|
||||
@ -1724,7 +1721,7 @@ const modifierPool: ModifierPool = {
|
||||
const { gameMode, gameData } = party[0].scene;
|
||||
if (gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) {
|
||||
return party.some(p => ((p.getSpeciesForm(true).speciesId in pokemonEvolutions) || (p.isFusion() && (p.getFusionSpeciesForm(true).speciesId in pokemonEvolutions)))
|
||||
&& !p.getHeldItems().some(i => i instanceof Modifiers.EvolutionStatBoosterModifier) && !p.isMax()) ? 10 : 0;
|
||||
&& !p.getHeldItems().some(i => i instanceof EvolutionStatBoosterModifier) && !p.isMax()) ? 10 : 0;
|
||||
}
|
||||
return 0;
|
||||
}),
|
||||
@ -1732,7 +1729,7 @@ const modifierPool: ModifierPool = {
|
||||
new WeightedModifierType(modifierTypes.LEEK, (party: Pokemon[]) => {
|
||||
const checkedSpecies = [ Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD ];
|
||||
// If a party member doesn't already have a Leek and is one of the relevant species, Leek can appear
|
||||
return party.some(p => !p.getHeldItems().some(i => i instanceof Modifiers.SpeciesCritBoosterModifier)
|
||||
return party.some(p => !p.getHeldItems().some(i => i instanceof SpeciesCritBoosterModifier)
|
||||
&& (checkedSpecies.includes(p.getSpeciesForm(true).speciesId)
|
||||
|| (p.isFusion() && checkedSpecies.includes(p.getFusionSpeciesForm(true).speciesId)))) ? 12 : 0;
|
||||
}, 12),
|
||||
@ -1740,7 +1737,7 @@ const modifierPool: ModifierPool = {
|
||||
const checkedAbilities = [Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.TOXIC_BOOST, Abilities.POISON_HEAL, Abilities.MAGIC_GUARD];
|
||||
const checkedMoves = [Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT];
|
||||
// If a party member doesn't already have one of these two orbs and has one of the above moves or abilities, the orb can appear
|
||||
return party.some(p => !p.getHeldItems().some(i => i instanceof Modifiers.TurnStatusEffectModifier)
|
||||
return party.some(p => !p.getHeldItems().some(i => i instanceof TurnStatusEffectModifier)
|
||||
&& (checkedAbilities.some(a => p.hasAbility(a, false, true))
|
||||
|| p.getMoveset(true).some(m => m && checkedMoves.includes(m.moveId)))) ? 10 : 0;
|
||||
}, 10),
|
||||
@ -1748,13 +1745,13 @@ const modifierPool: ModifierPool = {
|
||||
const checkedAbilities = [Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.FLARE_BOOST, Abilities.MAGIC_GUARD];
|
||||
const checkedMoves = [Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT];
|
||||
// If a party member doesn't already have one of these two orbs and has one of the above moves or abilities, the orb can appear
|
||||
return party.some(p => !p.getHeldItems().some(i => i instanceof Modifiers.TurnStatusEffectModifier)
|
||||
return party.some(p => !p.getHeldItems().some(i => i instanceof TurnStatusEffectModifier)
|
||||
&& (checkedAbilities.some(a => p.hasAbility(a, false, true)) || p.getMoveset(true).some(m => m && checkedMoves.includes(m.moveId)))) ? 10 : 0;
|
||||
}, 10),
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB, (party: Pokemon[]) => {
|
||||
const checkedAbilities = [Abilities.WEAK_ARMOR, Abilities.CONTRARY, Abilities.MOODY, Abilities.ANGER_SHELL, Abilities.COMPETITIVE, Abilities.DEFIANT];
|
||||
const weightMultiplier = party.filter(
|
||||
p => !p.getHeldItems().some(i => i instanceof Modifiers.ResetNegativeStatStageModifier && i.stackCount >= i.getMaxHeldItemCount(p)) &&
|
||||
p => !p.getHeldItems().some(i => i instanceof ResetNegativeStatStageModifier && i.stackCount >= i.getMaxHeldItemCount(p)) &&
|
||||
(checkedAbilities.some(a => p.hasAbility(a, false, true)) || p.getMoveset(true).some(m => m && selfStatLowerMoves.includes(m.moveId)))).length;
|
||||
// If a party member has one of the above moves or abilities and doesn't have max herbs, the herb will appear more frequently
|
||||
return 0 * (weightMultiplier ? 2 : 1) + (weightMultiplier ? weightMultiplier * 0 : 0);
|
||||
@ -2247,7 +2244,7 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
||||
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
||||
}
|
||||
|
||||
export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: Modifiers.PersistentModifier[], scene: BattleScene): Modifiers.EnemyPersistentModifier {
|
||||
export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: PersistentModifier[], scene: BattleScene): EnemyPersistentModifier {
|
||||
let tierStackCount: number;
|
||||
switch (tier) {
|
||||
case ModifierTier.ULTRA:
|
||||
@ -2264,30 +2261,30 @@ export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers:
|
||||
const retryCount = 50;
|
||||
let candidate = getNewModifierTypeOption([], ModifierPoolType.ENEMY_BUFF, tier);
|
||||
let r = 0;
|
||||
let matchingModifier: Modifiers.PersistentModifier | undefined;
|
||||
let matchingModifier: PersistentModifier | undefined;
|
||||
while (++r < retryCount && (matchingModifier = enemyModifiers.find(m => m.type.id === candidate?.type?.id)) && matchingModifier.getMaxStackCount(scene) < matchingModifier.stackCount + (r < 10 ? tierStackCount : 1)) {
|
||||
candidate = getNewModifierTypeOption([], ModifierPoolType.ENEMY_BUFF, tier);
|
||||
}
|
||||
|
||||
const modifier = candidate?.type?.newModifier() as Modifiers.EnemyPersistentModifier;
|
||||
const modifier = candidate?.type?.newModifier() as EnemyPersistentModifier;
|
||||
modifier.stackCount = tierStackCount;
|
||||
|
||||
return modifier;
|
||||
}
|
||||
|
||||
export function getEnemyModifierTypesForWave(waveIndex: integer, count: integer, party: EnemyPokemon[], poolType: ModifierPoolType.WILD | ModifierPoolType.TRAINER, upgradeChance: integer = 0): PokemonHeldItemModifierType[] {
|
||||
const ret = new Array(count).fill(0).map(() => getNewModifierTypeOption(party, poolType, undefined, upgradeChance && !Utils.randSeedInt(upgradeChance) ? 1 : 0)?.type as PokemonHeldItemModifierType);
|
||||
const ret = new Array(count).fill(0).map(() => getNewModifierTypeOption(party, poolType, undefined, upgradeChance && !randSeedInt(upgradeChance) ? 1 : 0)?.type as PokemonHeldItemModifierType);
|
||||
if (!(waveIndex % 1000)) {
|
||||
ret.push(getModifierType(modifierTypes.MINI_BLACK_HOLE) as PokemonHeldItemModifierType);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function getDailyRunStarterModifiers(party: PlayerPokemon[]): Modifiers.PokemonHeldItemModifier[] {
|
||||
const ret: Modifiers.PokemonHeldItemModifier[] = [];
|
||||
export function getDailyRunStarterModifiers(party: PlayerPokemon[]): PokemonHeldItemModifier[] {
|
||||
const ret: PokemonHeldItemModifier[] = [];
|
||||
for (const p of party) {
|
||||
for (let m = 0; m < 3; m++) {
|
||||
const tierValue = Utils.randSeedInt(64);
|
||||
const tierValue = randSeedInt(64);
|
||||
|
||||
let tier: ModifierTier;
|
||||
if (tierValue > 25) {
|
||||
@ -2302,7 +2299,7 @@ export function getDailyRunStarterModifiers(party: PlayerPokemon[]): Modifiers.P
|
||||
tier = ModifierTier.MASTER;
|
||||
}
|
||||
|
||||
const modifier = getNewModifierTypeOption(party, ModifierPoolType.DAILY_STARTER, tier)?.type?.newModifier(p) as Modifiers.PokemonHeldItemModifier;
|
||||
const modifier = getNewModifierTypeOption(party, ModifierPoolType.DAILY_STARTER, tier)?.type?.newModifier(p) as PokemonHeldItemModifier;
|
||||
ret.push(modifier);
|
||||
}
|
||||
}
|
||||
@ -2341,7 +2338,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
|
||||
break;
|
||||
}
|
||||
if (tier === undefined) {
|
||||
const tierValue = Utils.randSeedInt(1024);
|
||||
const tierValue = randSeedInt(1024);
|
||||
if (!upgradeCount) {
|
||||
upgradeCount = 0;
|
||||
}
|
||||
@ -2350,7 +2347,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
|
||||
const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4));
|
||||
let upgraded = false;
|
||||
do {
|
||||
upgraded = Utils.randSeedInt(upgradeOdds) < 4;
|
||||
upgraded = randSeedInt(upgradeOdds) < 4;
|
||||
if (upgraded) {
|
||||
upgradeCount++;
|
||||
}
|
||||
@ -2382,7 +2379,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
|
||||
const partyShinyCount = party.filter(p => p.isShiny() && !p.isFainted()).length;
|
||||
const upgradeOdds = Math.floor(32 / ((partyShinyCount + 2) / 2));
|
||||
while (modifierPool.hasOwnProperty(tier + upgradeCount + 1) && modifierPool[tier + upgradeCount + 1].length) {
|
||||
if (!Utils.randSeedInt(upgradeOdds)) {
|
||||
if (!randSeedInt(upgradeOdds)) {
|
||||
upgradeCount++;
|
||||
} else {
|
||||
break;
|
||||
@ -2397,7 +2394,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
|
||||
|
||||
const tierThresholds = Object.keys(thresholds[tier]);
|
||||
const totalWeight = parseInt(tierThresholds[tierThresholds.length - 1]);
|
||||
const value = Utils.randSeedInt(totalWeight);
|
||||
const value = randSeedInt(totalWeight);
|
||||
let index: integer | undefined;
|
||||
for (const t of tierThresholds) {
|
||||
const threshold = parseInt(t);
|
||||
@ -2457,9 +2454,9 @@ export class ModifierTypeOption {
|
||||
*/
|
||||
export function getPartyLuckValue(party: Pokemon[]): integer {
|
||||
if (party[0].scene.gameMode.isDaily) {
|
||||
const DailyLuck = new Utils.NumberHolder(0);
|
||||
const DailyLuck = new NumberHolder(0);
|
||||
party[0].scene.executeWithSeedOffset(() => {
|
||||
DailyLuck.value = Utils.randSeedInt(15); // Random number between 0 and 14
|
||||
DailyLuck.value = randSeedInt(15); // Random number between 0 and 14
|
||||
}, 0, party[0].scene.seed);
|
||||
return DailyLuck.value;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -57,7 +57,7 @@ export class BattleEndPhase extends BattlePhase {
|
||||
if (m instanceof LapsingPokemonHeldItemModifier) {
|
||||
args.push(this.scene.getPokemonById(m.pokemonId));
|
||||
}
|
||||
if (!m.lapse(args)) {
|
||||
if (!m.lapse(...args)) {
|
||||
this.scene.removeModifier(m);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export class BerryPhase extends FieldPhase {
|
||||
|
||||
this.executeForAll((pokemon) => {
|
||||
const hasUsableBerry = !!this.scene.findModifier((m) => {
|
||||
return m instanceof BerryModifier && m.shouldApply([pokemon]);
|
||||
return m instanceof BerryModifier && m.shouldApply(pokemon);
|
||||
}, pokemon.isPlayer());
|
||||
|
||||
if (hasUsableBerry) {
|
||||
@ -29,7 +29,7 @@ export class BerryPhase extends FieldPhase {
|
||||
new CommonAnimPhase(this.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.USE_ITEM)
|
||||
);
|
||||
|
||||
for (const berryModifier of this.scene.applyModifiers(BerryModifier, pokemon.isPlayer(), pokemon) as BerryModifier[]) {
|
||||
for (const berryModifier of this.scene.applyModifiers(BerryModifier, pokemon.isPlayer(), pokemon)) {
|
||||
if (berryModifier.consumed) {
|
||||
if (!--berryModifier.stackCount) {
|
||||
this.scene.removeModifier(berryModifier);
|
||||
|
@ -2,7 +2,7 @@ import BattleScene from "#app/battle-scene";
|
||||
import { TurnCommand, BattleType } from "#app/battle";
|
||||
import { TrappedTag, EncoreTag } from "#app/data/battler-tags";
|
||||
import { MoveTargetSet, getMoveTargets } from "#app/data/move";
|
||||
import { speciesStarters } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { BattlerTagType } from "#app/enums/battler-tag-type";
|
||||
import { Biome } from "#app/enums/biome";
|
||||
@ -126,7 +126,7 @@ export class CommandPhase extends FieldPhase {
|
||||
}
|
||||
break;
|
||||
case Command.BALL:
|
||||
const notInDex = (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarters).length - 1);
|
||||
const notInDex = (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1);
|
||||
if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || this.scene.gameMode.isFreshStartChallenge() || notInDex )) {
|
||||
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
|
@ -1,17 +1,17 @@
|
||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { Phase } from "../phase";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { SpeciesFormEvolution } from "../data/pokemon-evolutions";
|
||||
import EvolutionSceneHandler from "../ui/evolution-scene-handler";
|
||||
import * as Utils from "../utils";
|
||||
import { Mode } from "../ui/ui";
|
||||
import { cos, sin } from "../field/anims";
|
||||
import { PlayerPokemon } from "../field/pokemon";
|
||||
import { getTypeRgb } from "../data/type";
|
||||
import { Phase } from "#app/phase";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
|
||||
import EvolutionSceneHandler from "#app/ui/evolution-scene-handler";
|
||||
import * as Utils from "#app/utils";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import { cos, sin } from "#app/field/anims";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { getTypeRgb } from "#app/data/type";
|
||||
import i18next from "i18next";
|
||||
import { getPokemonNameWithAffix } from "../messages";
|
||||
import { LearnMovePhase } from "./learn-move-phase";
|
||||
import { EndEvolutionPhase } from "./end-evolution-phase";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
|
||||
|
||||
export class EvolutionPhase extends Phase {
|
||||
protected pokemon: PlayerPokemon;
|
||||
|
@ -2,7 +2,7 @@ import { clientSessionId } from "#app/account";
|
||||
import { BattleType } from "#app/battle";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { getCharVariantFromDialogue } from "#app/data/dialogue";
|
||||
import { pokemonEvolutions } from "#app/data/pokemon-evolutions";
|
||||
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { trainerConfigs } from "#app/data/trainer-config";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
|
@ -4,7 +4,7 @@ import { applyPreAttackAbAttrs, AddSecondStrikeAbAttr, IgnoreMoveEffectsAbAttr,
|
||||
import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag";
|
||||
import { MoveAnim } from "#app/data/battle-anims";
|
||||
import { BattlerTagLapseType, DamageProtectedTag, ProtectedTag, SemiInvulnerableTag, SubstituteTag } from "#app/data/battler-tags";
|
||||
import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger, ChargeAttr, MoveCategory, NoEffectAttr, HitsTagAttr } from "#app/data/move";
|
||||
import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger, ChargeAttr, MoveCategory, NoEffectAttr, HitsTagAttr, ToxicAccuracyAttr } from "#app/data/move";
|
||||
import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms";
|
||||
import { BattlerTagType } from "#app/enums/battler-tag-type";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
@ -14,6 +14,7 @@ import { PokemonMultiHitModifier, FlinchChanceModifier, EnemyAttackStatusEffectC
|
||||
import i18next from "i18next";
|
||||
import * as Utils from "#app/utils";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
import { Type } from "#app/data/type";
|
||||
|
||||
export class MoveEffectPhase extends PokemonPhase {
|
||||
public move: PokemonMove;
|
||||
@ -354,12 +355,14 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
} else {
|
||||
// Queue message for number of hits made by multi-move
|
||||
// If multi-hit attack only hits once, still want to render a message
|
||||
const hitsTotal = user.turnData.hitCount! - Math.max(user.turnData.hitsLeft!, 0); // TODO: are those bangs correct?
|
||||
const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0);
|
||||
if (hitsTotal > 1 || (user.turnData.hitsLeft && user.turnData.hitsLeft > 0)) {
|
||||
// If there are multiple hits, or if there are hits of the multi-hit move left
|
||||
this.scene.queueMessage(i18next.t("battle:attackHitsCount", { count: hitsTotal }));
|
||||
}
|
||||
this.scene.applyModifiers(HitHealModifier, this.player, user);
|
||||
// Clear all cached move effectiveness values among targets
|
||||
this.getTargets().forEach((target) => target.turnData.moveEffectiveness = null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -402,7 +405,10 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
}
|
||||
|
||||
const semiInvulnerableTag = target.getTag(SemiInvulnerableTag);
|
||||
if (semiInvulnerableTag && !this.move.getMove().getAttrs(HitsTagAttr).some(hta => hta.tagType === semiInvulnerableTag.tagType)) {
|
||||
if (semiInvulnerableTag
|
||||
&& !this.move.getMove().getAttrs(HitsTagAttr).some(hta => hta.tagType === semiInvulnerableTag.tagType)
|
||||
&& !(this.move.getMove().getAttrs(ToxicAccuracyAttr) && user.isOfType(Type.POISON))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
import { ShowAbilityPhase } from "./show-ability-phase";
|
||||
|
||||
/**
|
||||
* Cures the party of all non-volatile status conditions, shows a message
|
||||
* @param {BattleScene} scene The current scene
|
||||
* @param {Pokemon} user The user of the move that cures the party
|
||||
* @param {string} message The message that should be displayed
|
||||
* @param {Abilities} abilityCondition Pokemon with this ability will not be affected ie. Soundproof
|
||||
*/
|
||||
export class PartyStatusCurePhase extends BattlePhase {
|
||||
private user: Pokemon;
|
||||
private message: string;
|
||||
private abilityCondition: Abilities;
|
||||
|
||||
constructor(scene: BattleScene, user: Pokemon, message: string, abilityCondition: Abilities) {
|
||||
super(scene);
|
||||
|
||||
this.user = user;
|
||||
this.message = message;
|
||||
this.abilityCondition = abilityCondition;
|
||||
}
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
for (const pokemon of this.scene.getParty()) {
|
||||
if (!pokemon.isOnField() || pokemon === this.user) {
|
||||
pokemon.resetStatus(false);
|
||||
pokemon.updateInfo(true);
|
||||
} else {
|
||||
if (!pokemon.hasAbility(this.abilityCondition)) {
|
||||
pokemon.resetStatus();
|
||||
pokemon.updateInfo(true);
|
||||
} else {
|
||||
// Manually show ability bar, since we're not hooked into the targeting system
|
||||
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.id, pokemon.getPassiveAbility()?.id === this.abilityCondition));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.message) {
|
||||
this.scene.queueMessage(this.message);
|
||||
}
|
||||
this.end();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { biomeLinks, getBiomeName } from "#app/data/biomes";
|
||||
import { biomeLinks, getBiomeName } from "#app/data/balance/biomes";
|
||||
import { Biome } from "#app/enums/biome";
|
||||
import { MoneyInterestModifier, MapModifier } from "#app/modifier/modifier";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
|
@ -44,7 +44,7 @@ export class WeatherEffectPhase extends CommonAnimPhase {
|
||||
return;
|
||||
}
|
||||
|
||||
const damage = Math.ceil(pokemon.getMaxHp() / 16);
|
||||
const damage = Utils.toDmgValue(pokemon.getMaxHp() / 16);
|
||||
|
||||
this.scene.queueMessage(getWeatherDamageMessage(this.weather?.weatherType!, pokemon)!); // TODO: are those bangs correct?
|
||||
pokemon.damageAndUpdate(damage, HitResult.EFFECTIVE, false, false, true);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Modifier } from "typescript";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { TurnHeldItemTransferModifier } from "../modifier/modifier";
|
||||
import { pokemonEvolutions } from "#app/data/pokemon-evolutions";
|
||||
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import i18next from "i18next";
|
||||
import * as Utils from "../utils";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
|
@ -1,52 +1,53 @@
|
||||
import i18next from "i18next";
|
||||
import BattleScene, { bypassLogin, PokeballCounts } from "../battle-scene";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "../field/pokemon";
|
||||
import { pokemonPrevolutions } from "../data/pokemon-evolutions";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, noStarterFormKeys, speciesStarters } from "../data/pokemon-species";
|
||||
import * as Utils from "../utils";
|
||||
import BattleScene, { bypassLogin, PokeballCounts } from "#app/battle-scene";
|
||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
|
||||
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpecies, noStarterFormKeys } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import * as Utils from "#app/utils";
|
||||
import Overrides from "#app/overrides";
|
||||
import PokemonData from "./pokemon-data";
|
||||
import PersistentModifierData from "./modifier-data";
|
||||
import ArenaData from "./arena-data";
|
||||
import { Unlockables } from "./unlockables";
|
||||
import { GameModes, getGameMode } from "../game-mode";
|
||||
import { BattleType } from "../battle";
|
||||
import TrainerData from "./trainer-data";
|
||||
import { trainerConfigs } from "../data/trainer-config";
|
||||
import { resetSettings, setSetting, SettingKeys } from "./settings/settings";
|
||||
import { achvs } from "./achv";
|
||||
import EggData from "./egg-data";
|
||||
import { Egg } from "../data/egg";
|
||||
import { vouchers, VoucherType } from "./voucher";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import PersistentModifierData from "#app/system/modifier-data";
|
||||
import ArenaData from "#app/system/arena-data";
|
||||
import { Unlockables } from "#app/system/unlockables";
|
||||
import { GameModes, getGameMode } from "#app/game-mode";
|
||||
import { BattleType } from "#app/battle";
|
||||
import TrainerData from "#app/system/trainer-data";
|
||||
import { trainerConfigs } from "#app/data/trainer-config";
|
||||
import { resetSettings, setSetting, SettingKeys } from "#app/system/settings/settings";
|
||||
import { achvs } from "#app/system/achv";
|
||||
import EggData from "#app/system/egg-data";
|
||||
import { Egg } from "#app/data/egg";
|
||||
import { vouchers, VoucherType } from "#app/system/voucher";
|
||||
import { AES, enc } from "crypto-js";
|
||||
import { Mode } from "../ui/ui";
|
||||
import { clientSessionId, loggedInUser, updateUserInfo } from "../account";
|
||||
import { Nature } from "../data/nature";
|
||||
import { GameStats } from "./game-stats";
|
||||
import { Tutorial } from "../tutorial";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { allMoves } from "../data/move";
|
||||
import { TrainerVariant } from "../field/trainer";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import { clientSessionId, loggedInUser, updateUserInfo } from "#app/account";
|
||||
import { Nature } from "#app/data/nature";
|
||||
import { GameStats } from "#app/system/game-stats";
|
||||
import { Tutorial } from "#app/tutorial";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { TrainerVariant } from "#app/field/trainer";
|
||||
import { Variant } from "#app/data/variant";
|
||||
import { setSettingGamepad, SettingGamepad, settingGamepadDefaults } from "./settings/settings-gamepad";
|
||||
import { setSettingGamepad, SettingGamepad, settingGamepadDefaults } from "#app/system/settings/settings-gamepad";
|
||||
import { setSettingKeyboard, SettingKeyboard } from "#app/system/settings/settings-keyboard";
|
||||
import { TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena";
|
||||
import * as Modifier from "../modifier/modifier";
|
||||
import * as Modifier from "#app/modifier/modifier";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import ChallengeData from "./challenge-data";
|
||||
import ChallengeData from "#app/system/challenge-data";
|
||||
import { Device } from "#enums/devices";
|
||||
import { GameDataType } from "#enums/game-data-type";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { Species } from "#enums/species";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge";
|
||||
import { WeatherType } from "#app/enums/weather-type";
|
||||
import { WeatherType } from "#enums/weather-type";
|
||||
import { TerrainType } from "#app/data/terrain";
|
||||
import { OutdatedPhase } from "#app/phases/outdated-phase";
|
||||
import { ReloadSessionPhase } from "#app/phases/reload-session-phase";
|
||||
import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler";
|
||||
import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatches } from "./version-converter";
|
||||
import { MysteryEncounterSaveData } from "../data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatches } from "#app/system/version-converter";
|
||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PokerogueApiClearSessionData } from "#app/@types/pokerogue-api";
|
||||
|
||||
@ -1537,7 +1538,7 @@ export class GameData {
|
||||
private initStarterData(): void {
|
||||
const starterData: StarterData = {};
|
||||
|
||||
const starterSpeciesIds = Object.keys(speciesStarters).map(k => parseInt(k) as Species);
|
||||
const starterSpeciesIds = Object.keys(speciesStarterCosts).map(k => parseInt(k) as Species);
|
||||
|
||||
for (const speciesId of starterSpeciesIds) {
|
||||
starterData[speciesId] = {
|
||||
@ -1617,7 +1618,7 @@ export class GameData {
|
||||
dexEntry.caughtAttr |= dexAttr;
|
||||
|
||||
// Unlock ability
|
||||
if (speciesStarters.hasOwnProperty(species.speciesId)) {
|
||||
if (speciesStarterCosts.hasOwnProperty(species.speciesId)) {
|
||||
this.starterData[species.speciesId].abilityAttr |= pokemon.abilityIndex !== 1 || pokemon.species.ability2
|
||||
? 1 << pokemon.abilityIndex
|
||||
: AbilityAttr.ABILITY_HIDDEN;
|
||||
@ -1673,7 +1674,7 @@ export class GameData {
|
||||
}
|
||||
};
|
||||
|
||||
if (newCatch && speciesStarters.hasOwnProperty(species.speciesId)) {
|
||||
if (newCatch && speciesStarterCosts.hasOwnProperty(species.speciesId)) {
|
||||
if (!showMessage) {
|
||||
resolve(true);
|
||||
return;
|
||||
@ -1801,7 +1802,7 @@ export class GameData {
|
||||
}
|
||||
|
||||
getStarterCount(dexEntryPredicate: (entry: DexEntry) => boolean): integer {
|
||||
const starterKeys = Object.keys(speciesStarters);
|
||||
const starterKeys = Object.keys(speciesStarterCosts);
|
||||
let starterCount = 0;
|
||||
for (const s of starterKeys) {
|
||||
const starterDexEntry = this.dexData[s];
|
||||
@ -1875,7 +1876,7 @@ export class GameData {
|
||||
}
|
||||
|
||||
getSpeciesStarterValue(speciesId: Species): number {
|
||||
const baseValue = speciesStarters[speciesId];
|
||||
const baseValue = speciesStarterCosts[speciesId];
|
||||
let value = baseValue;
|
||||
|
||||
const decrementValue = (value: number) => {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { Species } from "#app/enums/species";
|
||||
@ -106,4 +107,26 @@ describe("Abilities - Tera Shell", () => {
|
||||
expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp() - 40);
|
||||
}
|
||||
);
|
||||
|
||||
it(
|
||||
"should change the effectiveness of all strikes of a multi-strike move",
|
||||
async () => {
|
||||
game.override.enemyMoveset([Moves.DOUBLE_HIT]);
|
||||
|
||||
await game.classicMode.startBattle([Species.SNORLAX]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
vi.spyOn(playerPokemon, "apply");
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.move.forceHit();
|
||||
for (let i = 0; i < 2; i++) {
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
expect(playerPokemon.apply).toHaveLastReturnedWith(HitResult.NOT_VERY_EFFECTIVE);
|
||||
}
|
||||
expect(playerPokemon.apply).toHaveReturnedTimes(2);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -39,7 +39,7 @@ describe("Weather - Hail", () => {
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
game.scene.getField(true).forEach(pokemon => {
|
||||
expect(pokemon.hp).toBeLessThan(pokemon.getMaxHp() - Math.floor(pokemon.getMaxHp() / 16));
|
||||
expect(pokemon.hp).toBe(pokemon.getMaxHp() - Math.max(Math.floor(pokemon.getMaxHp() / 16), 1));
|
||||
});
|
||||
});
|
||||
|
||||
@ -56,6 +56,20 @@ describe("Weather - Hail", () => {
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp());
|
||||
expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp() - Math.floor(enemyPokemon.getMaxHp() / 16));
|
||||
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp() - Math.max(Math.floor(enemyPokemon.getMaxHp() / 16), 1));
|
||||
});
|
||||
|
||||
it("does not inflict damage to Ice type Pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.CLOYSTER]);
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp());
|
||||
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp() - Math.max(Math.floor(enemyPokemon.getMaxHp() / 16), 1));
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { WeatherType } from "#app/data/weather";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Stat } from "#app/enums/stat";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
@ -37,7 +39,7 @@ describe("Weather - Sandstorm", () => {
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
game.scene.getField(true).forEach(pokemon => {
|
||||
expect(pokemon.hp).toBeLessThan(pokemon.getMaxHp() - Math.floor(pokemon.getMaxHp() / 16));
|
||||
expect(pokemon.hp).toBe(pokemon.getMaxHp() - Math.max(Math.floor(pokemon.getMaxHp() / 16), 1));
|
||||
});
|
||||
});
|
||||
|
||||
@ -53,6 +55,37 @@ describe("Weather - Sandstorm", () => {
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
|
||||
expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp());
|
||||
expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp() - Math.floor(enemyPokemon.getMaxHp() / 16));
|
||||
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp() - Math.max(Math.floor(enemyPokemon.getMaxHp() / 16), 1));
|
||||
});
|
||||
|
||||
it("does not inflict damage to Rock, Ground and Steel type Pokemon", async () => {
|
||||
game.override
|
||||
.battleType("double")
|
||||
.enemySpecies(Species.SANDSHREW)
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.enemyAbility(Abilities.BALL_FETCH);
|
||||
|
||||
await game.classicMode.startBattle([Species.ROCKRUFF, Species.KLINK]);
|
||||
|
||||
game.move.select(Moves.SPLASH, 0);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
game.scene.getField(true).forEach(pokemon => {
|
||||
expect(pokemon.hp).toBe(pokemon.getMaxHp());
|
||||
});
|
||||
});
|
||||
|
||||
it("increases Rock type Pokemon Sp.Def by 50%", async () => {
|
||||
await game.classicMode.startBattle([Species.ROCKRUFF]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
const playerSpdef = playerPokemon.getStat(Stat.SPDEF);
|
||||
expect(playerPokemon.getEffectiveStat(Stat.SPDEF)).toBe(Math.floor(playerSpdef * 1.5));
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
const enemySpdef = enemyPokemon.getStat(Stat.SPDEF);
|
||||
expect(enemyPokemon.getEffectiveStat(Stat.SPDEF)).toBe(enemySpdef);
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { pokemonEvolutions, SpeciesFormEvolution, SpeciesWildEvolutionDelay } from "#app/data/pokemon-evolutions";
|
||||
import { pokemonEvolutions, SpeciesFormEvolution, SpeciesWildEvolutionDelay } from "#app/data/balance/pokemon-evolutions";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { Species } from "#app/enums/species";
|
||||
|
101
src/test/moves/aromatherapy.test.ts
Normal file
101
src/test/moves/aromatherapy.test.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import { StatusEffect } from "#app/enums/status-effect";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest";
|
||||
|
||||
describe("Moves - Aromatherapy", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset([Moves.AROMATHERAPY, Moves.SPLASH])
|
||||
.statusEffect(StatusEffect.BURN)
|
||||
.battleType("double")
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH);
|
||||
});
|
||||
|
||||
it("should cure status effect of the user, its ally, and all party pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]);
|
||||
const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty();
|
||||
|
||||
vi.spyOn(leftPlayer, "resetStatus");
|
||||
vi.spyOn(rightPlayer, "resetStatus");
|
||||
vi.spyOn(partyPokemon, "resetStatus");
|
||||
|
||||
game.move.select(Moves.AROMATHERAPY, 0);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(rightPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(partyPokemon.resetStatus).toHaveBeenCalledOnce();
|
||||
|
||||
expect(leftPlayer.status?.effect).toBeUndefined();
|
||||
expect(rightPlayer.status?.effect).toBeUndefined();
|
||||
expect(partyPokemon.status?.effect).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should not cure status effect of the target/target's allies", async () => {
|
||||
game.override.enemyStatusEffect(StatusEffect.BURN);
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA]);
|
||||
const [leftOpp, rightOpp] = game.scene.getEnemyField();
|
||||
|
||||
vi.spyOn(leftOpp, "resetStatus");
|
||||
vi.spyOn(rightOpp, "resetStatus");
|
||||
|
||||
game.move.select(Moves.AROMATHERAPY, 0);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftOpp.resetStatus).toHaveBeenCalledTimes(0);
|
||||
expect(rightOpp.resetStatus).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(leftOpp.status?.effect).toBeTruthy();
|
||||
expect(rightOpp.status?.effect).toBeTruthy();
|
||||
|
||||
expect(leftOpp.status?.effect).toBe(StatusEffect.BURN);
|
||||
expect(rightOpp.status?.effect).toBe(StatusEffect.BURN);
|
||||
});
|
||||
|
||||
it("should not cure status effect of allies ON FIELD with Sap Sipper, should still cure allies in party", async () => {
|
||||
game.override.ability(Abilities.SAP_SIPPER);
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]);
|
||||
const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty();
|
||||
|
||||
vi.spyOn(leftPlayer, "resetStatus");
|
||||
vi.spyOn(rightPlayer, "resetStatus");
|
||||
vi.spyOn(partyPokemon, "resetStatus");
|
||||
|
||||
game.move.select(Moves.AROMATHERAPY, 0);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(rightPlayer.resetStatus).toHaveBeenCalledTimes(0);
|
||||
expect(partyPokemon.resetStatus).toHaveBeenCalledOnce();
|
||||
|
||||
expect(leftPlayer.status?.effect).toBeUndefined();
|
||||
expect(rightPlayer.status?.effect).toBe(StatusEffect.BURN);
|
||||
expect(partyPokemon.status?.effect).toBeUndefined();
|
||||
});
|
||||
});
|
101
src/test/moves/heal_bell.test.ts
Normal file
101
src/test/moves/heal_bell.test.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import { StatusEffect } from "#app/enums/status-effect";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest";
|
||||
|
||||
describe("Moves - Heal Bell", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset([Moves.HEAL_BELL, Moves.SPLASH])
|
||||
.statusEffect(StatusEffect.BURN)
|
||||
.battleType("double")
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH);
|
||||
});
|
||||
|
||||
it("should cure status effect of the user, its ally, and all party pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]);
|
||||
const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty();
|
||||
|
||||
vi.spyOn(leftPlayer, "resetStatus");
|
||||
vi.spyOn(rightPlayer, "resetStatus");
|
||||
vi.spyOn(partyPokemon, "resetStatus");
|
||||
|
||||
game.move.select(Moves.HEAL_BELL, 0);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(rightPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(partyPokemon.resetStatus).toHaveBeenCalledOnce();
|
||||
|
||||
expect(leftPlayer.status?.effect).toBeUndefined();
|
||||
expect(rightPlayer.status?.effect).toBeUndefined();
|
||||
expect(partyPokemon.status?.effect).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should not cure status effect of the target/target's allies", async () => {
|
||||
game.override.enemyStatusEffect(StatusEffect.BURN);
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA]);
|
||||
const [leftOpp, rightOpp] = game.scene.getEnemyField();
|
||||
|
||||
vi.spyOn(leftOpp, "resetStatus");
|
||||
vi.spyOn(rightOpp, "resetStatus");
|
||||
|
||||
game.move.select(Moves.HEAL_BELL, 0);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftOpp.resetStatus).toHaveBeenCalledTimes(0);
|
||||
expect(rightOpp.resetStatus).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(leftOpp.status?.effect).toBeTruthy();
|
||||
expect(rightOpp.status?.effect).toBeTruthy();
|
||||
|
||||
expect(leftOpp.status?.effect).toBe(StatusEffect.BURN);
|
||||
expect(rightOpp.status?.effect).toBe(StatusEffect.BURN);
|
||||
});
|
||||
|
||||
it("should not cure status effect of allies ON FIELD with Soundproof, should still cure allies in party", async () => {
|
||||
game.override.ability(Abilities.SOUNDPROOF);
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]);
|
||||
const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty();
|
||||
|
||||
vi.spyOn(leftPlayer, "resetStatus");
|
||||
vi.spyOn(rightPlayer, "resetStatus");
|
||||
vi.spyOn(partyPokemon, "resetStatus");
|
||||
|
||||
game.move.select(Moves.HEAL_BELL, 0);
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(rightPlayer.resetStatus).toHaveBeenCalledTimes(0);
|
||||
expect(partyPokemon.resetStatus).toHaveBeenCalledOnce();
|
||||
|
||||
expect(leftPlayer.status?.effect).toBeUndefined();
|
||||
expect(rightPlayer.status?.effect).toBe(StatusEffect.BURN);
|
||||
expect(partyPokemon.status?.effect).toBeUndefined();
|
||||
});
|
||||
});
|
74
src/test/moves/scale_shot.test.ts
Normal file
74
src/test/moves/scale_shot.test.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { DamagePhase } from "#app/phases/damage-phase";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
import { TurnEndPhase } from "#app/phases/turn-end-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { Stat } from "#enums/stat";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest";
|
||||
|
||||
describe("Moves - Scale Shot", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset([Moves.SCALE_SHOT])
|
||||
.battleType("single")
|
||||
.disableCrits()
|
||||
.starterSpecies(Species.MINCCINO)
|
||||
.ability(Abilities.NO_GUARD)
|
||||
.passiveAbility(Abilities.SKILL_LINK)
|
||||
.enemyAbility(Abilities.SHEER_FORCE)
|
||||
.enemyPassiveAbility(Abilities.STALL)
|
||||
.enemyMoveset(Moves.SKILL_SWAP)
|
||||
.enemyLevel(5);
|
||||
});
|
||||
|
||||
it("applies stat changes after last hit", async () => {
|
||||
await game.classicMode.startBattle([Species.FORRETRESS]);
|
||||
const minccino = game.scene.getPlayerPokemon()!;
|
||||
game.move.select(Moves.SCALE_SHOT);
|
||||
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||
await game.phaseInterceptor.to(DamagePhase);
|
||||
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||
expect (minccino?.getStatStage(Stat.DEF)).toBe(0);
|
||||
expect (minccino?.getStatStage(Stat.SPD)).toBe(0);
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
expect (minccino.getStatStage(Stat.DEF)).toBe(-1);
|
||||
expect (minccino.getStatStage(Stat.SPD)).toBe(1);
|
||||
});
|
||||
|
||||
it("unaffected by sheer force", async () => {
|
||||
await game.classicMode.startBattle([Species.WOBBUFFET]);
|
||||
const minccino = game.scene.getPlayerPokemon()!;
|
||||
const wobbuffet = game.scene.getEnemyPokemon()!;
|
||||
wobbuffet.setStat(Stat.HP, 100, true);
|
||||
wobbuffet.hp = 100;
|
||||
game.move.select(Moves.SCALE_SHOT);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
const hpafter1 = wobbuffet.hp;
|
||||
//effect not nullified by sheer force
|
||||
expect (minccino.getStatStage(Stat.DEF)).toBe(-1);
|
||||
expect (minccino.getStatStage(Stat.SPD)).toBe(1);
|
||||
game.move.select(Moves.SCALE_SHOT);
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
const hpafter2 = wobbuffet.hp;
|
||||
//check damage not boosted- make damage before sheer force a little lower than theoretical boosted sheer force damage
|
||||
expect (100 - hpafter1).toBe(hpafter1 - hpafter2);
|
||||
});
|
||||
});
|
86
src/test/moves/sparkly_swirl.test.ts
Normal file
86
src/test/moves/sparkly_swirl.test.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { StatusEffect } from "#app/enums/status-effect";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
describe("Moves - Sparkly Swirl", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({ type: Phaser.HEADLESS });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.enemySpecies(Species.SHUCKLE)
|
||||
.enemyLevel(100)
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.moveset([Moves.SPARKLY_SWIRL, Moves.SPLASH])
|
||||
.ability(Abilities.BALL_FETCH);
|
||||
|
||||
vi.spyOn(allMoves[Moves.SPARKLY_SWIRL], "accuracy", "get").mockReturnValue(100);
|
||||
});
|
||||
|
||||
it("should cure status effect of the user, its ally, and all party pokemon", async () => {
|
||||
game.override
|
||||
.battleType("double")
|
||||
.statusEffect(StatusEffect.BURN);
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]);
|
||||
const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty();
|
||||
const leftOpp = game.scene.getEnemyPokemon()!;
|
||||
|
||||
vi.spyOn(leftPlayer, "resetStatus");
|
||||
vi.spyOn(rightPlayer, "resetStatus");
|
||||
vi.spyOn(partyPokemon, "resetStatus");
|
||||
|
||||
game.move.select(Moves.SPARKLY_SWIRL, 0, leftOpp.getBattlerIndex());
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(rightPlayer.resetStatus).toHaveBeenCalledOnce();
|
||||
expect(partyPokemon.resetStatus).toHaveBeenCalledOnce();
|
||||
|
||||
expect(leftPlayer.status?.effect).toBeUndefined();
|
||||
expect(rightPlayer.status?.effect).toBeUndefined();
|
||||
expect(partyPokemon.status?.effect).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should not cure status effect of the target/target's allies", async () => {
|
||||
game.override
|
||||
.battleType("double")
|
||||
.enemyStatusEffect(StatusEffect.BURN);
|
||||
await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA]);
|
||||
const [leftOpp, rightOpp] = game.scene.getEnemyField();
|
||||
|
||||
vi.spyOn(leftOpp, "resetStatus");
|
||||
vi.spyOn(rightOpp, "resetStatus");
|
||||
|
||||
game.move.select(Moves.SPARKLY_SWIRL, 0, leftOpp.getBattlerIndex());
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(leftOpp.resetStatus).toHaveBeenCalledTimes(0);
|
||||
expect(rightOpp.resetStatus).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(leftOpp.status?.effect).toBeTruthy();
|
||||
expect(rightOpp.status?.effect).toBeTruthy();
|
||||
|
||||
expect(leftOpp.status?.effect).toBe(StatusEffect.BURN);
|
||||
expect(rightOpp.status?.effect).toBe(StatusEffect.BURN);
|
||||
});
|
||||
});
|
98
src/test/moves/tera_starstorm.test.ts
Normal file
98
src/test/moves/tera_starstorm.test.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { Type } from "#app/data/type";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest";
|
||||
|
||||
describe("Moves - Tera Starstorm", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset([Moves.TERA_STARSTORM, Moves.SPLASH])
|
||||
.battleType("double")
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.enemyLevel(30)
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.startingHeldItems([{ name: "TERA_SHARD", type: Type.FIRE }]);
|
||||
});
|
||||
|
||||
it("changes type to Stellar when used by Terapagos in its Stellar Form", async () => {
|
||||
game.override.battleType("single");
|
||||
await game.classicMode.startBattle([Species.TERAPAGOS]);
|
||||
|
||||
const terapagos = game.scene.getPlayerPokemon()!;
|
||||
|
||||
vi.spyOn(terapagos, "getMoveType");
|
||||
|
||||
game.move.select(Moves.TERA_STARSTORM);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(terapagos.isTerastallized()).toBe(true);
|
||||
expect(terapagos.getMoveType).toHaveReturnedWith(Type.STELLAR);
|
||||
});
|
||||
|
||||
it("targets both opponents in a double battle when used by Terapagos in its Stellar Form", async () => {
|
||||
await game.classicMode.startBattle([Species.MAGIKARP, Species.TERAPAGOS]);
|
||||
|
||||
game.move.select(Moves.TERA_STARSTORM, 0, BattlerIndex.ENEMY);
|
||||
game.move.select(Moves.TERA_STARSTORM, 1);
|
||||
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
|
||||
|
||||
const enemyField = game.scene.getEnemyField();
|
||||
|
||||
// Pokemon other than Terapagos should not be affected - only hits one target
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
expect(enemyField.some(pokemon => pokemon.isFullHp())).toBe(true);
|
||||
|
||||
// Terapagos in Stellar Form should hit both targets
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
expect(enemyField.every(pokemon => pokemon.isFullHp())).toBe(false);
|
||||
});
|
||||
|
||||
it("applies the effects when Terapagos in Stellar Form is fused with another Pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.TERAPAGOS, Species.CHARMANDER, Species.MAGIKARP]);
|
||||
|
||||
const fusionedMon = game.scene.getParty()[0];
|
||||
const magikarp = game.scene.getParty()[2];
|
||||
|
||||
// Fuse party members (taken from PlayerPokemon.fuse(...) function)
|
||||
fusionedMon.fusionSpecies = magikarp.species;
|
||||
fusionedMon.fusionFormIndex = magikarp.formIndex;
|
||||
fusionedMon.fusionAbilityIndex = magikarp.abilityIndex;
|
||||
fusionedMon.fusionShiny = magikarp.shiny;
|
||||
fusionedMon.fusionVariant = magikarp.variant;
|
||||
fusionedMon.fusionGender = magikarp.gender;
|
||||
fusionedMon.fusionLuck = magikarp.luck;
|
||||
|
||||
vi.spyOn(fusionedMon, "getMoveType");
|
||||
|
||||
game.move.select(Moves.TERA_STARSTORM, 0);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
// Fusion and terastallized
|
||||
expect(fusionedMon.isFusion()).toBe(true);
|
||||
expect(fusionedMon.isTerastallized()).toBe(true);
|
||||
// Move effects should be applied
|
||||
expect(fusionedMon.getMoveType).toHaveReturnedWith(Type.STELLAR);
|
||||
expect(game.scene.getEnemyField().every(pokemon => pokemon.isFullHp())).toBe(false);
|
||||
});
|
||||
});
|
76
src/test/moves/toxic.test.ts
Normal file
76
src/test/moves/toxic.test.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { allMoves } from "#app/data/move";
|
||||
|
||||
describe("Moves - Toxic", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.battleType("single")
|
||||
.moveset(Moves.TOXIC)
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyMoveset(Moves.SPLASH);
|
||||
});
|
||||
|
||||
it("should be guaranteed to hit if user is Poison-type", async () => {
|
||||
vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(0);
|
||||
await game.classicMode.startBattle([Species.TOXAPEX]);
|
||||
|
||||
game.move.select(Moves.TOXIC);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.TOXIC);
|
||||
});
|
||||
|
||||
it("may miss if user is not Poison-type", async () => {
|
||||
vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(0);
|
||||
await game.classicMode.startBattle([Species.UMBREON]);
|
||||
|
||||
game.move.select(Moves.TOXIC);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.status).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should hit semi-invulnerable targets if user is Poison-type", async () => {
|
||||
vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(0);
|
||||
game.override.enemyMoveset(Moves.FLY);
|
||||
await game.classicMode.startBattle([Species.TOXAPEX]);
|
||||
|
||||
game.move.select(Moves.TOXIC);
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.TOXIC);
|
||||
});
|
||||
|
||||
it("should miss semi-invulnerable targets if user is not Poison-type", async () => {
|
||||
vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(-1);
|
||||
game.override.enemyMoveset(Moves.FLY);
|
||||
await game.classicMode.startBattle([Species.UMBREON]);
|
||||
|
||||
game.move.select(Moves.TOXIC);
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(game.scene.getEnemyPokemon()!.status).toBeUndefined();
|
||||
});
|
||||
});
|
@ -17,7 +17,7 @@ import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { speciesEggMoves } from "#app/data/egg-moves";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
|
@ -6,7 +6,8 @@ import { Species } from "#enums/species";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { getPokemonSpecies, speciesStarters } from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { Type } from "#app/data/type";
|
||||
import { getHighestLevelPlayerPokemon, getLowestLevelPlayerPokemon, getRandomPlayerPokemon, getRandomSpeciesByStarterTier, koPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { getEncounterText, queueEncounterMessage, showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
@ -209,7 +210,7 @@ describe("Mystery Encounter Utils", () => {
|
||||
const pokeSpecies = getPokemonSpecies(result);
|
||||
|
||||
expect(pokeSpecies.speciesId).toBe(result);
|
||||
expect(speciesStarters[result]).toBe(5);
|
||||
expect(speciesStarterCosts[result]).toBe(5);
|
||||
});
|
||||
|
||||
it("gets species for a starter tier range", () => {
|
||||
@ -217,8 +218,8 @@ describe("Mystery Encounter Utils", () => {
|
||||
const pokeSpecies = getPokemonSpecies(result);
|
||||
|
||||
expect(pokeSpecies.speciesId).toBe(result);
|
||||
expect(speciesStarters[result]).toBeGreaterThanOrEqual(5);
|
||||
expect(speciesStarters[result]).toBeLessThanOrEqual(8);
|
||||
expect(speciesStarterCosts[result]).toBeGreaterThanOrEqual(5);
|
||||
expect(speciesStarterCosts[result]).toBeLessThanOrEqual(8);
|
||||
});
|
||||
|
||||
it("excludes species from search", () => {
|
||||
|
@ -2,11 +2,11 @@ import "vitest-canvas-mock";
|
||||
|
||||
import { initLoggedInUser } from "#app/account";
|
||||
import { initAbilities } from "#app/data/ability";
|
||||
import { initBiomes } from "#app/data/biomes";
|
||||
import { initEggMoves } from "#app/data/egg-moves";
|
||||
import { initBiomes } from "#app/data/balance/biomes";
|
||||
import { initEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { initMoves } from "#app/data/move";
|
||||
import { initMysteryEncounters } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { initPokemonPrevolutions } from "#app/data/pokemon-evolutions";
|
||||
import { initPokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { initPokemonForms } from "#app/data/pokemon-forms";
|
||||
import { initSpecies } from "#app/data/pokemon-species";
|
||||
import { initAchievements } from "#app/system/achv";
|
||||
|
@ -8,7 +8,7 @@ import { VoucherType, getVoucherTypeIcon } from "../system/voucher";
|
||||
import { getPokemonSpecies } from "../data/pokemon-species";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import { Tutorial, handleTutorial } from "../tutorial";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { Button } from "#enums/buttons";
|
||||
import Overrides from "#app/overrides";
|
||||
import { GachaType } from "#app/enums/gacha-types";
|
||||
import i18next from "i18next";
|
||||
@ -99,7 +99,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
||||
|
||||
const gachaInfoContainer = this.scene.add.container(160, 46);
|
||||
|
||||
const currentLanguage = i18next.resolvedLanguage!; // TODO: is this bang correct?
|
||||
const currentLanguage = i18next.resolvedLanguage ?? "en";
|
||||
let gachaTextStyle = TextStyle.WINDOW_ALT;
|
||||
let gachaX = 4;
|
||||
let gachaY = 0;
|
||||
@ -217,7 +217,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
||||
{ multiplier: multiplierOne, description: `25 ${i18next.t("egg:pulls")}`, icon: getVoucherTypeIcon(VoucherType.GOLDEN) }
|
||||
];
|
||||
|
||||
const resolvedLanguage = i18next.resolvedLanguage ?? "en"; // TODO: is this bang correct?
|
||||
const resolvedLanguage = i18next.resolvedLanguage ?? "en";
|
||||
const pullOptionsText = pullOptions.map(option =>{
|
||||
const desc = option.description.split(" ");
|
||||
if (desc[0].length < 2) {
|
||||
|
@ -1,15 +1,15 @@
|
||||
import Phaser from "phaser";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
import UiHandler from "./ui-handler";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import * as Utils from "../utils";
|
||||
import { DexAttr, GameData } from "../system/game-data";
|
||||
import { speciesStarters } from "../data/pokemon-species";
|
||||
import {Button} from "#enums/buttons";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { TextStyle, addTextObject } from "#app/ui/text";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import UiHandler from "#app/ui/ui-handler";
|
||||
import { addWindow } from "#app/ui/ui-theme";
|
||||
import * as Utils from "#app/utils";
|
||||
import { DexAttr, GameData } from "#app/system/game-data";
|
||||
import { speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { Button } from "#enums/buttons";
|
||||
import i18next from "i18next";
|
||||
import { UiTheme } from "#app/enums/ui-theme";
|
||||
import { UiTheme } from "#enums/ui-theme";
|
||||
|
||||
interface DisplayStat {
|
||||
label_key?: string;
|
||||
@ -34,14 +34,14 @@ const displayStats: DisplayStats = {
|
||||
label_key: "starters",
|
||||
sourceFunc: gameData => {
|
||||
const starterCount = gameData.getStarterCount(d => !!d.caughtAttr);
|
||||
return `${starterCount} (${Math.floor((starterCount / Object.keys(speciesStarters).length) * 1000) / 10}%)`;
|
||||
return `${starterCount} (${Math.floor((starterCount / Object.keys(speciesStarterCosts).length) * 1000) / 10}%)`;
|
||||
}
|
||||
},
|
||||
shinyStartersUnlocked: {
|
||||
label_key: "shinyStarters",
|
||||
sourceFunc: gameData => {
|
||||
const starterCount = gameData.getStarterCount(d => !!(d.caughtAttr & DexAttr.SHINY));
|
||||
return `${starterCount} (${Math.floor((starterCount / Object.keys(speciesStarters).length) * 1000) / 10}%)`;
|
||||
return `${starterCount} (${Math.floor((starterCount / Object.keys(speciesStarterCosts).length) * 1000) / 10}%)`;
|
||||
}
|
||||
},
|
||||
dexSeen: {
|
||||
|
@ -1,22 +1,22 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import Pokemon, { MoveResult, PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "./text";
|
||||
import { Command } from "./command-ui-handler";
|
||||
import MessageUiHandler from "./message-ui-handler";
|
||||
import { Mode } from "./ui";
|
||||
import * as Utils from "../utils";
|
||||
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier, SwitchEffectTransferModifier } from "../modifier/modifier";
|
||||
import { allMoves, ForceSwitchOutAttr } from "../data/move";
|
||||
import { getGenderColor, getGenderSymbol } from "../data/gender";
|
||||
import { StatusEffect } from "../data/status-effect";
|
||||
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim-handler";
|
||||
import { pokemonEvolutions } from "../data/pokemon-evolutions";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import { SpeciesFormChangeItemTrigger, FormChangeItem } from "../data/pokemon-forms";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import Pokemon, { MoveResult, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "#app/ui/text";
|
||||
import { Command } from "#app/ui/command-ui-handler";
|
||||
import MessageUiHandler from "#app/ui/message-ui-handler";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import * as Utils from "#app/utils";
|
||||
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier, SwitchEffectTransferModifier } from "#app/modifier/modifier";
|
||||
import { allMoves, ForceSwitchOutAttr } from "#app/data/move";
|
||||
import { getGenderColor, getGenderSymbol } from "#app/data/gender";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-icon-anim-handler";
|
||||
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { addWindow } from "#app/ui/ui-theme";
|
||||
import { SpeciesFormChangeItemTrigger, FormChangeItem } from "#app/data/pokemon-forms";
|
||||
import { getVariantTint } from "#app/data/variant";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
import MoveInfoOverlay from "#app/ui/move-info-overlay";
|
||||
import i18next from "i18next";
|
||||
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
||||
import { Moves } from "#enums/moves";
|
||||
|
@ -1,14 +1,14 @@
|
||||
import PokemonInfoContainer from "./pokemon-info-container";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { Gender } from "../data/gender";
|
||||
import { Type } from "../data/type";
|
||||
import * as Utils from "../utils";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { speciesEggMoves } from "#app/data/egg-moves";
|
||||
import PokemonInfoContainer from "#app/ui/pokemon-info-container";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { Type } from "#app/data/type";
|
||||
import * as Utils from "#app/utils";
|
||||
import { TextStyle, addTextObject } from "#app/ui/text";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { Species } from "#app/enums/species";
|
||||
import { Species } from "#enums/species";
|
||||
import { getEggTierForSpecies } from "#app/data/egg";
|
||||
import { starterColors } from "../battle-scene";
|
||||
import { starterColors } from "#app/battle-scene";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import { EggHatchData } from "#app/data/egg-hatch-data";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
|
@ -1,51 +1,54 @@
|
||||
import { BattleSceneEventType, CandyUpgradeNotificationChangedEvent } from "../events/battle-scene";
|
||||
import { pokemonPrevolutions } from "#app/data/pokemon-evolutions";
|
||||
import { BattleSceneEventType, CandyUpgradeNotificationChangedEvent } from "#app/events/battle-scene";
|
||||
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { Variant, getVariantTint, getVariantIcon } from "#app/data/variant";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import i18next from "i18next";
|
||||
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
||||
import BattleScene, { starterColors } from "../battle-scene";
|
||||
import { allAbilities } from "../data/ability";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { GrowthRate, getGrowthRateColor } from "../data/exp";
|
||||
import { Gender, getGenderColor, getGenderSymbol } from "../data/gender";
|
||||
import { allMoves } from "../data/move";
|
||||
import { Nature, getNatureName } from "../data/nature";
|
||||
import { pokemonFormChanges } from "../data/pokemon-forms";
|
||||
import { LevelMoves, pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "../data/pokemon-level-moves";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities, POKERUS_STARTER_COUNT, getPokerusStarters } from "../data/pokemon-species";
|
||||
import { Type } from "../data/type";
|
||||
import { GameModes } from "../game-mode";
|
||||
import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterMoveset, StarterAttributes, StarterPreferences, StarterPrefs } from "../system/game-data";
|
||||
import { Tutorial, handleTutorial } from "../tutorial";
|
||||
import * as Utils from "../utils";
|
||||
import { OptionSelectItem } from "./abstact-option-select-ui-handler";
|
||||
import MessageUiHandler from "./message-ui-handler";
|
||||
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim-handler";
|
||||
import { StatsContainer } from "./stats-container";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import BattleScene, { starterColors } from "#app/battle-scene";
|
||||
import { allAbilities } from "#app/data/ability";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { GrowthRate, getGrowthRateColor } from "#app/data/exp";
|
||||
import { Gender, getGenderColor, getGenderSymbol } from "#app/data/gender";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { Nature, getNatureName } from "#app/data/nature";
|
||||
import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
||||
import { LevelMoves, pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "#app/data/balance/pokemon-level-moves";
|
||||
import PokemonSpecies, { allSpecies, getPokemonSpeciesForm, getPokerusStarters } from "#app/data/pokemon-species";
|
||||
import { getStarterValueFriendshipCap, speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters";
|
||||
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
||||
import { Type } from "#app/data/type";
|
||||
import { GameModes } from "#app/game-mode";
|
||||
import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterMoveset, StarterAttributes, StarterPreferences, StarterPrefs } from "#app/system/game-data";
|
||||
import { Tutorial, handleTutorial } from "#app/tutorial";
|
||||
import * as Utils from "#app/utils";
|
||||
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import MessageUiHandler from "#app/ui/message-ui-handler";
|
||||
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-icon-anim-handler";
|
||||
import { StatsContainer } from "#app/ui/stats-container";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject } from "#app/ui/text";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import { addWindow } from "#app/ui/ui-theme";
|
||||
import { Egg } from "#app/data/egg";
|
||||
import Overrides from "#app/overrides";
|
||||
import { SettingKeyboard } from "#app/system/settings/settings-keyboard";
|
||||
import { Passive as PassiveAttr } from "#enums/passive";
|
||||
import * as Challenge from "../data/challenge";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
import * as Challenge from "#app/data/challenge";
|
||||
import MoveInfoOverlay from "#app/ui/move-info-overlay";
|
||||
import { getEggTierForSpecies } from "#app/data/egg";
|
||||
import { Device } from "#enums/devices";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { EggSourceType } from "#app/enums/egg-source-types";
|
||||
import AwaitableUiHandler from "./awaitable-ui-handler";
|
||||
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "./dropdown";
|
||||
import { StarterContainer } from "./starter-container";
|
||||
import { DropDownColumn, FilterBar } from "./filter-bar";
|
||||
import { ScrollBar } from "./scroll-bar";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import AwaitableUiHandler from "#app/ui/awaitable-ui-handler";
|
||||
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#app/ui/dropdown";
|
||||
import { StarterContainer } from "#app/ui/starter-container";
|
||||
import { DropDownColumn, FilterBar } from "#app/ui/filter-bar";
|
||||
import { ScrollBar } from "#app/ui/scroll-bar";
|
||||
import { SelectChallengePhase } from "#app/phases/select-challenge-phase";
|
||||
import { TitlePhase } from "#app/phases/title-phase";
|
||||
import { Abilities } from "#app/enums/abilities";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { getPassiveCandyCount, getValueReductionCandyCounts, getSameSpeciesEggCandyCounts } from "#app/data/balance/starters";
|
||||
|
||||
export type StarterSelectCallback = (starters: Starter[]) => void;
|
||||
|
||||
@ -119,19 +122,6 @@ const languageSettings: { [key: string]: LanguageSetting } = {
|
||||
},
|
||||
};
|
||||
|
||||
const starterCandyCosts: { passive: integer, costReduction: [integer, integer], egg: integer }[] = [
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 1 Cost
|
||||
{ passive: 40, costReduction: [25, 60], egg: 30 }, // 2 Cost
|
||||
{ passive: 35, costReduction: [20, 50], egg: 25 }, // 3 Cost
|
||||
{ passive: 30, costReduction: [15, 40], egg: 20 }, // 4 Cost
|
||||
{ passive: 25, costReduction: [12, 35], egg: 18 }, // 5 Cost
|
||||
{ passive: 20, costReduction: [10, 30], egg: 15 }, // 6 Cost
|
||||
{ passive: 15, costReduction: [8, 20], egg: 12 }, // 7 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 8 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 9 Cost
|
||||
{ passive: 10, costReduction: [5, 15], egg: 10 }, // 10 Cost
|
||||
];
|
||||
|
||||
const valueReductionMax = 2;
|
||||
|
||||
// Position of UI elements
|
||||
@ -142,18 +132,6 @@ const teamWindowY = 18;
|
||||
const teamWindowWidth = 34;
|
||||
const teamWindowHeight = 132;
|
||||
|
||||
function getPassiveCandyCount(baseValue: integer): integer {
|
||||
return starterCandyCosts[baseValue - 1].passive;
|
||||
}
|
||||
|
||||
function getValueReductionCandyCounts(baseValue: integer): [integer, integer] {
|
||||
return starterCandyCosts[baseValue - 1].costReduction;
|
||||
}
|
||||
|
||||
function getSameSpeciesEggCandyCounts(baseValue: integer): integer {
|
||||
return starterCandyCosts[baseValue - 1].egg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the starter position for a Pokemon of a given UI index
|
||||
* @param index UI index to calculate the starter position of
|
||||
@ -358,8 +336,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
setup() {
|
||||
const ui = this.getUi();
|
||||
const currentLanguage = i18next.resolvedLanguage ?? "en"; // TODO: is this bang correct?
|
||||
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)) ?? "en"; // TODO: is this bang correct?
|
||||
const currentLanguage = i18next.resolvedLanguage ?? "en";
|
||||
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)) ?? "en";
|
||||
const textSettings = languageSettings[langSettingKey];
|
||||
|
||||
this.starterSelectContainer = this.scene.add.container(0, -this.scene.game.canvas.height / 6);
|
||||
@ -658,7 +636,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
starterBoxContainer.add(this.cursorObj);
|
||||
|
||||
for (const species of allSpecies) {
|
||||
if (!speciesStarters.hasOwnProperty(species.speciesId) || !species.isObtainable()) {
|
||||
if (!speciesStarterCosts.hasOwnProperty(species.speciesId) || !species.isObtainable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1112,7 +1090,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
// Get this species ID's starter data
|
||||
const starterData = this.scene.gameData.starterData[speciesId];
|
||||
|
||||
return starterData.candyCount >= getPassiveCandyCount(speciesStarters[speciesId])
|
||||
return starterData.candyCount >= getPassiveCandyCount(speciesStarterCosts[speciesId])
|
||||
&& !(starterData.passiveAttr & PassiveAttr.UNLOCKED);
|
||||
}
|
||||
|
||||
@ -1125,7 +1103,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
// Get this species ID's starter data
|
||||
const starterData = this.scene.gameData.starterData[speciesId];
|
||||
|
||||
return starterData.candyCount >= getValueReductionCandyCounts(speciesStarters[speciesId])[starterData.valueReduction]
|
||||
return starterData.candyCount >= getValueReductionCandyCounts(speciesStarterCosts[speciesId])[starterData.valueReduction]
|
||||
&& starterData.valueReduction < valueReductionMax;
|
||||
}
|
||||
|
||||
@ -1138,7 +1116,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
// Get this species ID's starter data
|
||||
const starterData = this.scene.gameData.starterData[speciesId];
|
||||
|
||||
return starterData.candyCount >= getSameSpeciesEggCandyCounts(speciesStarters[speciesId]);
|
||||
return starterData.candyCount >= getSameSpeciesEggCandyCounts(speciesStarterCosts[speciesId]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1732,7 +1710,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
// Unlock passive option
|
||||
if (!(passiveAttr & PassiveAttr.UNLOCKED)) {
|
||||
const passiveCost = getPassiveCandyCount(speciesStarters[this.lastSpecies.speciesId]);
|
||||
const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.lastSpecies.speciesId]);
|
||||
options.push({
|
||||
label: `x${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")} (${allAbilities[starterPassiveAbilities[this.lastSpecies.speciesId]].name})`,
|
||||
handler: () => {
|
||||
@ -1768,7 +1746,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
// Reduce cost option
|
||||
const valueReduction = starterData.valueReduction;
|
||||
if (valueReduction < valueReductionMax) {
|
||||
const reductionCost = getValueReductionCandyCounts(speciesStarters[this.lastSpecies.speciesId])[valueReduction];
|
||||
const reductionCost = getValueReductionCandyCounts(speciesStarterCosts[this.lastSpecies.speciesId])[valueReduction];
|
||||
options.push({
|
||||
label: `x${reductionCost} ${i18next.t("starterSelectUiHandler:reduceCost")}`,
|
||||
handler: () => {
|
||||
@ -1802,7 +1780,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
}
|
||||
|
||||
// Same species egg menu option.
|
||||
const sameSpeciesEggCost = getSameSpeciesEggCandyCounts(speciesStarters[this.lastSpecies.speciesId]);
|
||||
const sameSpeciesEggCost = getSameSpeciesEggCandyCounts(speciesStarterCosts[this.lastSpecies.speciesId]);
|
||||
options.push({
|
||||
label: `x${sameSpeciesEggCost} ${i18next.t("starterSelectUiHandler:sameSpeciesEgg")}`,
|
||||
handler: () => {
|
||||
@ -2723,7 +2701,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
currentFriendship = 0;
|
||||
}
|
||||
|
||||
const friendshipCap = getStarterValueFriendshipCap(speciesStarters[speciesId]);
|
||||
const friendshipCap = getStarterValueFriendshipCap(speciesStarterCosts[speciesId]);
|
||||
|
||||
return { currentFriendship, friendshipCap };
|
||||
}
|
||||
@ -3356,7 +3334,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
updateStarterValueLabel(starter: StarterContainer): void {
|
||||
const speciesId = starter.species.speciesId;
|
||||
const baseStarterValue = speciesStarters[speciesId];
|
||||
const baseStarterValue = speciesStarterCosts[speciesId];
|
||||
const starterValue = this.scene.gameData.getSpeciesStarterValue(speciesId);
|
||||
starter.cost = starterValue;
|
||||
let valueStr = starterValue.toString();
|
||||
|
@ -1,28 +1,28 @@
|
||||
import BattleScene, { starterColors } from "../battle-scene";
|
||||
import { Mode } from "./ui";
|
||||
import UiHandler from "./ui-handler";
|
||||
import * as Utils from "../utils";
|
||||
import { PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { getStarterValueFriendshipCap, speciesStarters } from "../data/pokemon-species";
|
||||
import BattleScene, { starterColors } from "#app/battle-scene";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import UiHandler from "#app/ui/ui-handler";
|
||||
import * as Utils from "#app/utils";
|
||||
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { argbFromRgba } from "@material/material-color-utilities";
|
||||
import { Type, getTypeRgb } from "../data/type";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject, getBBCodeFrag } from "./text";
|
||||
import Move, { MoveCategory } from "../data/move";
|
||||
import { getPokeballAtlasKey } from "../data/pokeball";
|
||||
import { getGenderColor, getGenderSymbol } from "../data/gender";
|
||||
import { getLevelRelExp, getLevelTotalExp } from "../data/exp";
|
||||
import { PokemonHeldItemModifier } from "../modifier/modifier";
|
||||
import { StatusEffect } from "../data/status-effect";
|
||||
import { getBiomeName } from "../data/biomes";
|
||||
import { Nature, getNatureName, getNatureStatMultiplier } from "../data/nature";
|
||||
import { loggedInUser } from "../account";
|
||||
import { Type, getTypeRgb } from "#app/data/type";
|
||||
import { TextStyle, addBBCodeTextObject, addTextObject, getBBCodeFrag } from "#app/ui/text";
|
||||
import Move, { MoveCategory } from "#app/data/move";
|
||||
import { getPokeballAtlasKey } from "#app/data/pokeball";
|
||||
import { getGenderColor, getGenderSymbol } from "#app/data/gender";
|
||||
import { getLevelRelExp, getLevelTotalExp } from "#app/data/exp";
|
||||
import { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { StatusEffect } from "#app/data/status-effect";
|
||||
import { getBiomeName } from "#app/data/balance/biomes";
|
||||
import { Nature, getNatureName, getNatureStatMultiplier } from "#app/data/nature";
|
||||
import { loggedInUser } from "#app/account";
|
||||
import { Variant, getVariantTint } from "#app/data/variant";
|
||||
import {Button} from "#enums/buttons";
|
||||
import { Ability } from "../data/ability";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { Ability } from "#app/data/ability";
|
||||
import i18next from "i18next";
|
||||
import {modifierSortFunc} from "../modifier/modifier";
|
||||
import { modifierSortFunc } from "#app/modifier/modifier";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { Stat, PERMANENT_STATS, getStatKey } from "#app/enums/stat";
|
||||
import { Stat, PERMANENT_STATS, getStatKey } from "#enums/stat";
|
||||
|
||||
enum Page {
|
||||
PROFILE,
|
||||
@ -87,6 +87,10 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
private moveAccuracyText: Phaser.GameObjects.Text;
|
||||
private moveCategoryIcon: Phaser.GameObjects.Sprite;
|
||||
private summaryPageTransitionContainer: Phaser.GameObjects.Container;
|
||||
private friendshipShadow: Phaser.GameObjects.Sprite;
|
||||
private friendshipText: Phaser.GameObjects.Text;
|
||||
private friendshipIcon: Phaser.GameObjects.Sprite;
|
||||
private friendshipOverlay: Phaser.GameObjects.Sprite;
|
||||
|
||||
private descriptionScrollTween: Phaser.Tweens.Tween | null;
|
||||
private moveCursorBlinkTimer: Phaser.Time.TimerEvent | null;
|
||||
@ -187,6 +191,25 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.candyCountText.setOrigin(0, 0);
|
||||
this.summaryContainer.add(this.candyCountText);
|
||||
|
||||
this.friendshipIcon = this.scene.add.sprite(13, -60, "friendship");
|
||||
this.friendshipIcon.setScale(0.8);
|
||||
this.summaryContainer.add(this.friendshipIcon);
|
||||
|
||||
this.friendshipOverlay = this.scene.add.sprite(13, -60, "friendship_overlay");
|
||||
this.friendshipOverlay.setScale(0.8);
|
||||
this.summaryContainer.add(this.friendshipOverlay);
|
||||
|
||||
this.friendshipShadow = this.scene.add.sprite(13, -60, "friendship");
|
||||
this.friendshipShadow.setTint(0x000000);
|
||||
this.friendshipShadow.setAlpha(0.50);
|
||||
this.friendshipShadow.setScale(0.8);
|
||||
this.friendshipShadow.setInteractive(new Phaser.Geom.Rectangle(0, 0, 16, 16), Phaser.Geom.Rectangle.Contains);
|
||||
this.summaryContainer.add(this.friendshipShadow);
|
||||
|
||||
this.friendshipText = addTextObject(this.scene, 20, -66, "x0", TextStyle.WINDOW_ALT, { fontSize: "76px" });
|
||||
this.friendshipText.setOrigin(0, 0);
|
||||
this.summaryContainer.add(this.friendshipText);
|
||||
|
||||
this.championRibbon = this.scene.add.image(88, -146, "champion_ribbon");
|
||||
this.championRibbon.setOrigin(0, 0);
|
||||
//this.championRibbon.setScale(0.8);
|
||||
@ -292,6 +315,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.candyIcon.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[0])));
|
||||
this.candyOverlay.setTint(argbFromRgba(Utils.rgbHexToRgba(colorScheme[1])));
|
||||
|
||||
|
||||
this.numberText.setText(Utils.padInt(this.pokemon.species.speciesId, 4));
|
||||
this.numberText.setColor(this.getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD));
|
||||
this.numberText.setShadowColor(this.getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD, true));
|
||||
@ -333,7 +357,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
currentFriendship = 0;
|
||||
}
|
||||
|
||||
const friendshipCap = getStarterValueFriendshipCap(speciesStarters[this.pokemon.species.getRootSpeciesId()]);
|
||||
const friendshipCap = getStarterValueFriendshipCap(speciesStarterCosts[this.pokemon.species.getRootSpeciesId()]);
|
||||
const candyCropY = 16 - (16 * (currentFriendship / friendshipCap));
|
||||
|
||||
if (this.candyShadow.visible) {
|
||||
@ -345,6 +369,15 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
|
||||
this.candyShadow.setCrop(0, 0, 16, candyCropY);
|
||||
|
||||
if (this.friendshipShadow.visible) {
|
||||
this.friendshipShadow.on("pointerover", () => this.scene.ui.showTooltip("", `${i18next.t("pokemonSummary:friendship")}`, true));
|
||||
this.friendshipShadow.on("pointerout", () => this.scene.ui.hideTooltip());
|
||||
}
|
||||
|
||||
this.friendshipText.setText(`${this.pokemon?.friendship || "0"} / 255`);
|
||||
|
||||
this.friendshipShadow.setCrop(0, 0, 16, 16 - (16 * ((this.pokemon?.friendship || 0) / 255)));
|
||||
|
||||
const doubleShiny = isFusion && this.pokemon.shiny && this.pokemon.fusionShiny;
|
||||
const baseVariant = !doubleShiny ? this.pokemon.getVariant() : this.pokemon.variant;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user