mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-06 07:29:30 +02:00
Replace remaining Modifiers with Rewards (#6091)
* Changing remaining Modifiers to Consumables, and renaming ModifierType to Reward * Renamed modifier files and moved them into items folder * Using rewards in most places * Removed consumables in favor of using rewards directly * Renamed RewardTier to RarityTier * Reward ids, function to match rewards * Getting reward tiers from player pool still * Messing around with parameters of Reward.apply() * Always requiring player pokemon in rewards * Fixing some functions in select-reward-phase and battle-scene * Fixed various post-merge issues * Fixed most localization strings (accidentally broken by replacing modifierType with reward) * Fixed tests for select reward phase * Using Pokemon.hasSpecies() * Zero weight for trainer items rewards which are already max stack * Cleaning up SelectRewardPhase, held item rewards behave the same as any PokemonReward * Cleaned up some functions * Introduced RewardCategoryId, distributed RewardIds * Utility `is` functions for rewards * Minor fixes * Moved `HeldItemEffect` to its own file * rmade some todo comments * Adding a big comment * Added tsdocs and removed `RewardClass` * undid breaking changes * added TODO * Moved matchingRewards function to reward-utils.ts * Added RewardGenerator classes for mints and tera shards * Introducing default rarity tiers for trainer items and rewards * RewardFunc now can return RewardGenerator * Moved pool reward functions to their own file, plus other utility files * Fixed WeightedModifier to work with the new RewardFunc * Fixed wrong type import * Shifting trainer item and reward ids to avoid overlaps * Added some types * Updated comment in reward.ts * Added strong typing ot item maps * added type safety to held item name map --------- Co-authored-by: Bertie690 <taylormw163@gmail.com> Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com>
This commit is contained in:
parent
d3f2659cdf
commit
466c4aede2
@ -183,7 +183,7 @@ input:-internal-autofill-selected {
|
||||
/* Show #apadStats only in battle and shop */
|
||||
#touchControls:not([data-ui-mode="COMMAND"]):not([data-ui-mode="FIGHT"]):not(
|
||||
[data-ui-mode="BALL"]
|
||||
):not([data-ui-mode="TARGET_SELECT"]):not([data-ui-mode="MODIFIER_SELECT"])
|
||||
):not([data-ui-mode="TARGET_SELECT"]):not([data-ui-mode="REWARD_SELECT"])
|
||||
#apadStats {
|
||||
display: none;
|
||||
}
|
||||
|
@ -24,15 +24,15 @@ export interface AbilityTranslationEntries {
|
||||
[key: string]: AbilityTranslationEntry;
|
||||
}
|
||||
|
||||
export interface ModifierTypeTranslationEntry {
|
||||
export interface RewardTranslationEntry {
|
||||
name?: string;
|
||||
description?: string;
|
||||
extra?: SimpleTranslationEntries;
|
||||
}
|
||||
|
||||
export interface ModifierTypeTranslationEntries {
|
||||
ModifierType: { [key: string]: ModifierTypeTranslationEntry };
|
||||
SpeciesBoosterItem: { [key: string]: ModifierTypeTranslationEntry };
|
||||
export interface RewardTranslationEntries {
|
||||
Reward: { [key: string]: RewardTranslationEntry };
|
||||
SpeciesBoosterItem: { [key: string]: RewardTranslationEntry };
|
||||
AttackTypeBoosterItem: SimpleTranslationEntries;
|
||||
TempStatStageBoosterItem: SimpleTranslationEntries;
|
||||
BaseStatBoosterItem: SimpleTranslationEntries;
|
||||
|
@ -1,31 +0,0 @@
|
||||
// Intentionally re-exports `ModifierConstructorMap` from `modifier.ts`
|
||||
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { ModifierConstructorMap } from "#modifiers/modifier";
|
||||
import type { ModifierType, WeightedModifierType } from "#modifiers/modifier-type";
|
||||
|
||||
export type ModifierTypeFunc = () => ModifierType;
|
||||
export type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: number) => number;
|
||||
|
||||
export type { ModifierConstructorMap } from "#modifiers/modifier";
|
||||
|
||||
/**
|
||||
* Map of modifier names to their respective instance types
|
||||
*/
|
||||
export type ModifierInstanceMap = {
|
||||
[K in keyof ModifierConstructorMap]: InstanceType<ModifierConstructorMap[K]>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Union type of all modifier constructors.
|
||||
*/
|
||||
export type ModifierClass = ModifierConstructorMap[keyof ModifierConstructorMap];
|
||||
|
||||
/**
|
||||
* Union type of all modifier names as strings.
|
||||
*/
|
||||
export type ModifierString = keyof ModifierConstructorMap;
|
||||
|
||||
export type ModifierPool = {
|
||||
[tier: string]: WeightedModifierType[];
|
||||
};
|
23
src/@types/rewards.ts
Normal file
23
src/@types/rewards.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { RewardId } from "#enums/reward-id";
|
||||
import type { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { Reward, RewardGenerator } from "#items/reward";
|
||||
|
||||
export type RewardFunc = () => Reward | RewardGenerator;
|
||||
export type WeightedRewardWeightFunc = (party: Pokemon[], rerollCount?: number) => number;
|
||||
|
||||
export type RewardPoolId = RewardId | HeldItemId | TrainerItemId;
|
||||
|
||||
export type RewardPoolEntry = {
|
||||
id: RewardPoolId;
|
||||
weight: number | WeightedRewardWeightFunc;
|
||||
};
|
||||
|
||||
export type RewardPool = {
|
||||
[tier: string]: RewardPoolEntry[];
|
||||
};
|
||||
|
||||
export interface RewardPoolWeights {
|
||||
[tier: string]: number[];
|
||||
}
|
@ -53,8 +53,8 @@ import { ExpGainsSpeed } from "#enums/exp-gains-speed";
|
||||
import { ExpNotification } from "#enums/exp-notification";
|
||||
import { FormChangeItem } from "#enums/form-change-item";
|
||||
import { GameModes } from "#enums/game-modes";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import { HeldItemPoolType, ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { MoneyFormat } from "#enums/money-format";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
@ -65,6 +65,7 @@ import { PlayerGender } from "#enums/player-gender";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import type { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { HeldItemPoolType, RewardPoolType } from "#enums/reward-pool-type";
|
||||
import { ShopCursorTarget } from "#enums/shop-cursor-target";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
@ -82,9 +83,10 @@ import { PokemonSpriteSparkleHandler } from "#field/pokemon-sprite-sparkle-handl
|
||||
import { Trainer } from "#field/trainer";
|
||||
import { applyHeldItems } from "#items/all-held-items";
|
||||
import { type ApplyTrainerItemsParams, applyTrainerItems } from "#items/apply-trainer-items";
|
||||
import { HeldItemEffect } from "#items/held-item";
|
||||
import type { HeldItemConfiguration } from "#items/held-item-data-types";
|
||||
import { assignEnemyHeldItemsForWave, assignItemsFromConfiguration } from "#items/held-item-pool";
|
||||
import type { Reward } from "#items/reward";
|
||||
import { getRewardPoolForType } from "#items/reward-pool-utils";
|
||||
import { type EnemyAttackStatusEffectChanceTrainerItem, TrainerItemEffect } from "#items/trainer-item";
|
||||
import {
|
||||
isTrainerItemPool,
|
||||
@ -94,15 +96,6 @@ import {
|
||||
} from "#items/trainer-item-data-types";
|
||||
import { TrainerItemManager } from "#items/trainer-item-manager";
|
||||
import { getNewTrainerItemFromPool } from "#items/trainer-item-pool";
|
||||
import type { Modifier } from "#modifiers/modifier";
|
||||
import {
|
||||
ConsumableModifier,
|
||||
ConsumablePokemonModifier,
|
||||
FusePokemonModifier,
|
||||
PokemonHpRestoreModifier,
|
||||
RememberMoveModifier,
|
||||
} from "#modifiers/modifier";
|
||||
import { getLuckString, getLuckTextTint, getPartyLuckValue } from "#modifiers/modifier-type";
|
||||
import { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
||||
import { MysteryEncounterSaveData } from "#mystery-encounters/mystery-encounter-save-data";
|
||||
import { allMysteryEncounters, mysteryEncountersByBiome } from "#mystery-encounters/mystery-encounters";
|
||||
@ -112,7 +105,7 @@ import { hasExpSprite } from "#sprites/sprite-utils";
|
||||
import type { Variant } from "#sprites/variant";
|
||||
import { clearVariantData, variantData } from "#sprites/variant";
|
||||
import type { Achv } from "#system/achv";
|
||||
import { achvs, HeldItemAchv, ModifierAchv, MoneyAchv } from "#system/achv";
|
||||
import { achvs, HeldItemAchv, MoneyAchv } from "#system/achv";
|
||||
import { GameData } from "#system/game-data";
|
||||
import { initGameSpeed } from "#system/game-speed";
|
||||
import type { PokemonData } from "#system/pokemon-data";
|
||||
@ -148,7 +141,7 @@ import {
|
||||
} from "#utils/common";
|
||||
import { deepMergeSpriteData } from "#utils/data";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
import { getModifierPoolForType } from "#utils/modifier-utils";
|
||||
import { getLuckString, getLuckTextTint, getPartyLuckValue } from "#utils/party";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import i18next from "i18next";
|
||||
import Phaser from "phaser";
|
||||
@ -267,7 +260,7 @@ export class BattleScene extends SceneBase {
|
||||
public arena: Arena;
|
||||
public gameMode: GameMode;
|
||||
public score: number;
|
||||
public lockModifierTiers: boolean;
|
||||
public lockRarityTiers: boolean;
|
||||
public trainer: Phaser.GameObjects.Sprite;
|
||||
public lastEnemyTrainer: Trainer | null;
|
||||
public currentBattle: Battle;
|
||||
@ -480,12 +473,12 @@ export class BattleScene extends SceneBase {
|
||||
this.enemyTrainerItems = new TrainerItemManager();
|
||||
|
||||
this.itemBar = new ItemBar();
|
||||
this.itemBar.setName("modifier-bar");
|
||||
this.itemBar.setName("item-bar");
|
||||
this.add.existing(this.itemBar);
|
||||
uiContainer.add(this.itemBar);
|
||||
|
||||
this.enemyItemBar = new ItemBar(true);
|
||||
this.enemyItemBar.setName("enemy-modifier-bar");
|
||||
this.enemyItemBar.setName("enemy-item-bar");
|
||||
this.add.existing(this.enemyItemBar);
|
||||
uiContainer.add(this.enemyItemBar);
|
||||
|
||||
@ -854,9 +847,9 @@ export class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ModifierBar of this scene, which is declared private and therefore not accessible elsewhere
|
||||
* Returns the ItemBar of this scene, which is declared private and therefore not accessible elsewhere
|
||||
* @param isEnemy - Whether to return the enemy modifier bar instead of the player bar; default `false`
|
||||
* @returns The {@linkcode ModifierBar} for the given side of the field
|
||||
* @returns The {@linkcode ItemBar} for the given side of the field
|
||||
*/
|
||||
getItemBar(isEnemy = false): ItemBar {
|
||||
return isEnemy ? this.enemyItemBar : this.itemBar;
|
||||
@ -1167,7 +1160,7 @@ export class BattleScene extends SceneBase {
|
||||
this.score = 0;
|
||||
this.money = 0;
|
||||
|
||||
this.lockModifierTiers = false;
|
||||
this.lockRarityTiers = false;
|
||||
|
||||
this.pokeballCounts = Object.fromEntries(
|
||||
getEnumValues(PokeballType)
|
||||
@ -1243,12 +1236,12 @@ export class BattleScene extends SceneBase {
|
||||
...allSpecies,
|
||||
...allMoves,
|
||||
...allAbilities,
|
||||
...getEnumValues(ModifierPoolType)
|
||||
.map(mpt => getModifierPoolForType(mpt))
|
||||
...getEnumValues(RewardPoolType)
|
||||
.map(mpt => getRewardPoolForType(mpt))
|
||||
.flatMap(mp =>
|
||||
Object.values(mp)
|
||||
.flat()
|
||||
.map(mt => mt.modifierType)
|
||||
.map(mt => mt.reward)
|
||||
.filter(mt => "localize" in mt)
|
||||
.map(lpb => lpb as unknown as Localizable),
|
||||
),
|
||||
@ -1987,11 +1980,11 @@ export class BattleScene extends SceneBase {
|
||||
});
|
||||
}
|
||||
|
||||
showEnemyModifierBar(): void {
|
||||
showEnemyItemBar(): void {
|
||||
this.enemyItemBar.setVisible(true);
|
||||
}
|
||||
|
||||
hideEnemyModifierBar(): void {
|
||||
hideEnemyItemBar(): void {
|
||||
this.enemyItemBar.setVisible(false);
|
||||
}
|
||||
|
||||
@ -2085,11 +2078,11 @@ export class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
updateUIPositions(): void {
|
||||
const enemyModifierCount = this.enemyItemBar.totalVisibleLength;
|
||||
const enemyItemCount = this.enemyItemBar.totalVisibleLength;
|
||||
const biomeWaveTextHeight = this.biomeWaveText.getBottomLeft().y - this.biomeWaveText.getTopLeft().y;
|
||||
this.biomeWaveText.setY(
|
||||
-(this.game.canvas.height / 6) +
|
||||
(enemyModifierCount ? (enemyModifierCount <= 12 ? 15 : 24) : 0) +
|
||||
(enemyItemCount ? (enemyItemCount <= 12 ? 15 : 24) : 0) +
|
||||
biomeWaveTextHeight / 2,
|
||||
);
|
||||
this.moneyText.setY(this.biomeWaveText.y + 10);
|
||||
@ -2641,56 +2634,19 @@ export class BattleScene extends SceneBase {
|
||||
applyTrainerItems(effect, this.trainerItems, params);
|
||||
}
|
||||
|
||||
addModifier(modifier: Modifier | null, playSound?: boolean, instant?: boolean, cost?: number): boolean {
|
||||
// We check against modifier.type to stop a bug related to loading in a pokemon that has a form change item, which prior to some patch
|
||||
// that changed form change modifiers worked, had previously set the `type` field to null.
|
||||
// TODO: This is not the right place to check for this; it should ideally go in a session migrator.
|
||||
if (!modifier || !modifier.type) {
|
||||
applyReward<T extends Reward>(reward: T, params: Parameters<T["apply"]>[0], playSound?: boolean): boolean {
|
||||
const soundName = reward.soundName;
|
||||
|
||||
if (playSound && !this.sound.get(soundName)) {
|
||||
this.playSound(soundName);
|
||||
}
|
||||
|
||||
if (!reward.shouldApply(params)) {
|
||||
return false;
|
||||
}
|
||||
let success = false;
|
||||
const soundName = modifier.type.soundName;
|
||||
this.validateAchvs(ModifierAchv, modifier);
|
||||
if (modifier instanceof ConsumableModifier) {
|
||||
if (playSound && !this.sound.get(soundName)) {
|
||||
this.playSound(soundName);
|
||||
}
|
||||
|
||||
if (modifier instanceof ConsumablePokemonModifier) {
|
||||
for (const p in this.party) {
|
||||
const pokemon = this.party[p];
|
||||
|
||||
const args: unknown[] = [];
|
||||
if (modifier instanceof PokemonHpRestoreModifier) {
|
||||
if (!(modifier as PokemonHpRestoreModifier).fainted) {
|
||||
const hpRestoreMultiplier = new NumberHolder(1);
|
||||
this.applyPlayerItems(TrainerItemEffect.HEALING_BOOSTER, { numberHolder: hpRestoreMultiplier });
|
||||
args.push(hpRestoreMultiplier.value);
|
||||
} else {
|
||||
args.push(1);
|
||||
}
|
||||
} else if (modifier instanceof FusePokemonModifier) {
|
||||
args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon);
|
||||
} else if (modifier instanceof RememberMoveModifier && !isNullOrUndefined(cost)) {
|
||||
args.push(cost);
|
||||
}
|
||||
|
||||
if (modifier.shouldApply(pokemon, ...args)) {
|
||||
const result = modifier.apply(pokemon, ...args);
|
||||
success ||= result;
|
||||
}
|
||||
}
|
||||
|
||||
this.party.map(p => p.updateInfo(instant));
|
||||
} else {
|
||||
const args = [this];
|
||||
if (modifier.shouldApply(...args)) {
|
||||
const result = modifier.apply(...args);
|
||||
success ||= result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
reward.apply(params);
|
||||
return true;
|
||||
}
|
||||
|
||||
addHeldItem(heldItemId: HeldItemId, pokemon: Pokemon, amount = 1, playSound?: boolean, ignoreUpdate?: boolean) {
|
||||
@ -2864,7 +2820,7 @@ export class BattleScene extends SceneBase {
|
||||
}
|
||||
let count = 0;
|
||||
for (let c = 0; c < chances; c++) {
|
||||
if (!randSeedInt(this.gameMode.getEnemyModifierChance(isBoss))) {
|
||||
if (!randSeedInt(this.gameMode.getEnemyItemChance(isBoss))) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@ -2887,7 +2843,7 @@ export class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all modifiers from enemy pokemon of {@linkcode PersistentModifier} type
|
||||
* Removes all items from enemy pokemon and trainers
|
||||
*/
|
||||
clearEnemyItems(): void {
|
||||
this.enemyTrainerItems.clearItems();
|
||||
@ -2911,7 +2867,7 @@ export class BattleScene extends SceneBase {
|
||||
this.updateUIPositions();
|
||||
}
|
||||
|
||||
setModifiersVisible(visible: boolean) {
|
||||
setItemsVisible(visible: boolean) {
|
||||
[this.itemBar, this.enemyItemBar].map(m => m.setVisible(visible));
|
||||
}
|
||||
|
||||
|
@ -10,15 +10,14 @@ import type { MoveId } from "#enums/move-id";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import type { PokeballType } from "#enums/pokeball";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { TrainerVariant } from "#enums/trainer-variant";
|
||||
import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import { Trainer } from "#field/trainer";
|
||||
import type { CustomRewardSettings } from "#items/reward-pool-utils";
|
||||
import { TrainerItemEffect } from "#items/trainer-item";
|
||||
import type { CustomModifierSettings } from "#modifiers/modifier-type";
|
||||
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
||||
import i18next from "#plugins/i18n";
|
||||
import { MusicPreference } from "#system/settings";
|
||||
@ -481,7 +480,7 @@ export class FixedBattleConfig {
|
||||
public getTrainer: GetTrainerFunc;
|
||||
public getEnemyParty: GetEnemyPartyFunc;
|
||||
public seedOffsetWaveIndex: number;
|
||||
public customModifierRewardSettings?: CustomModifierSettings;
|
||||
public customRewardSettings?: CustomRewardSettings;
|
||||
|
||||
setBattleType(battleType: BattleType): FixedBattleConfig {
|
||||
this.battleType = battleType;
|
||||
@ -508,8 +507,8 @@ export class FixedBattleConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
setCustomModifierRewards(customModifierRewardSettings: CustomModifierSettings) {
|
||||
this.customModifierRewardSettings = customModifierRewardSettings;
|
||||
setCustomRewards(customRewardSettings: CustomRewardSettings) {
|
||||
this.customRewardSettings = customRewardSettings;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
|
||||
@ -68591,324 +68591,324 @@ function transposeTmSpecies(): SpeciesTmMoves {
|
||||
export const speciesTmMoves: SpeciesTmMoves = transposeTmSpecies();
|
||||
|
||||
interface TmPoolTiers {
|
||||
[key: number]: RewardTier
|
||||
[key: number]: RarityTier
|
||||
}
|
||||
|
||||
export const tmPoolTiers: TmPoolTiers = {
|
||||
[MoveId.MEGA_PUNCH]: RewardTier.GREAT,
|
||||
[MoveId.PAY_DAY]: RewardTier.ULTRA,
|
||||
[MoveId.FIRE_PUNCH]: RewardTier.GREAT,
|
||||
[MoveId.ICE_PUNCH]: RewardTier.GREAT,
|
||||
[MoveId.THUNDER_PUNCH]: RewardTier.GREAT,
|
||||
[MoveId.SWORDS_DANCE]: RewardTier.COMMON,
|
||||
[MoveId.CUT]: RewardTier.COMMON,
|
||||
[MoveId.FLY]: RewardTier.COMMON,
|
||||
[MoveId.MEGA_KICK]: RewardTier.GREAT,
|
||||
[MoveId.BODY_SLAM]: RewardTier.GREAT,
|
||||
[MoveId.TAKE_DOWN]: RewardTier.GREAT,
|
||||
[MoveId.DOUBLE_EDGE]: RewardTier.ULTRA,
|
||||
[MoveId.PIN_MISSILE]: RewardTier.COMMON,
|
||||
[MoveId.ROAR]: RewardTier.COMMON,
|
||||
[MoveId.FLAMETHROWER]: RewardTier.ULTRA,
|
||||
[MoveId.HYDRO_PUMP]: RewardTier.ULTRA,
|
||||
[MoveId.SURF]: RewardTier.ULTRA,
|
||||
[MoveId.ICE_BEAM]: RewardTier.ULTRA,
|
||||
[MoveId.BLIZZARD]: RewardTier.ULTRA,
|
||||
[MoveId.PSYBEAM]: RewardTier.GREAT,
|
||||
[MoveId.HYPER_BEAM]: RewardTier.ULTRA,
|
||||
[MoveId.LOW_KICK]: RewardTier.COMMON,
|
||||
[MoveId.COUNTER]: RewardTier.COMMON,
|
||||
[MoveId.STRENGTH]: RewardTier.GREAT,
|
||||
[MoveId.SOLAR_BEAM]: RewardTier.ULTRA,
|
||||
[MoveId.FIRE_SPIN]: RewardTier.COMMON,
|
||||
[MoveId.THUNDERBOLT]: RewardTier.ULTRA,
|
||||
[MoveId.THUNDER_WAVE]: RewardTier.COMMON,
|
||||
[MoveId.THUNDER]: RewardTier.ULTRA,
|
||||
[MoveId.EARTHQUAKE]: RewardTier.ULTRA,
|
||||
[MoveId.DIG]: RewardTier.GREAT,
|
||||
[MoveId.TOXIC]: RewardTier.GREAT,
|
||||
[MoveId.PSYCHIC]: RewardTier.ULTRA,
|
||||
[MoveId.AGILITY]: RewardTier.COMMON,
|
||||
[MoveId.NIGHT_SHADE]: RewardTier.COMMON,
|
||||
[MoveId.SCREECH]: RewardTier.COMMON,
|
||||
[MoveId.DOUBLE_TEAM]: RewardTier.COMMON,
|
||||
[MoveId.CONFUSE_RAY]: RewardTier.COMMON,
|
||||
[MoveId.LIGHT_SCREEN]: RewardTier.COMMON,
|
||||
[MoveId.HAZE]: RewardTier.COMMON,
|
||||
[MoveId.REFLECT]: RewardTier.COMMON,
|
||||
[MoveId.FOCUS_ENERGY]: RewardTier.COMMON,
|
||||
[MoveId.METRONOME]: RewardTier.COMMON,
|
||||
[MoveId.SELF_DESTRUCT]: RewardTier.GREAT,
|
||||
[MoveId.FIRE_BLAST]: RewardTier.ULTRA,
|
||||
[MoveId.WATERFALL]: RewardTier.GREAT,
|
||||
[MoveId.SWIFT]: RewardTier.COMMON,
|
||||
[MoveId.AMNESIA]: RewardTier.COMMON,
|
||||
[MoveId.DREAM_EATER]: RewardTier.GREAT,
|
||||
[MoveId.LEECH_LIFE]: RewardTier.ULTRA,
|
||||
[MoveId.FLASH]: RewardTier.COMMON,
|
||||
[MoveId.EXPLOSION]: RewardTier.GREAT,
|
||||
[MoveId.REST]: RewardTier.COMMON,
|
||||
[MoveId.ROCK_SLIDE]: RewardTier.GREAT,
|
||||
[MoveId.TRI_ATTACK]: RewardTier.ULTRA,
|
||||
[MoveId.SUPER_FANG]: RewardTier.COMMON,
|
||||
[MoveId.SUBSTITUTE]: RewardTier.COMMON,
|
||||
[MoveId.THIEF]: RewardTier.GREAT,
|
||||
[MoveId.SNORE]: RewardTier.COMMON,
|
||||
[MoveId.CURSE]: RewardTier.COMMON,
|
||||
[MoveId.REVERSAL]: RewardTier.COMMON,
|
||||
[MoveId.SPITE]: RewardTier.COMMON,
|
||||
[MoveId.PROTECT]: RewardTier.COMMON,
|
||||
[MoveId.SCARY_FACE]: RewardTier.COMMON,
|
||||
[MoveId.SLUDGE_BOMB]: RewardTier.GREAT,
|
||||
[MoveId.MUD_SLAP]: RewardTier.COMMON,
|
||||
[MoveId.SPIKES]: RewardTier.COMMON,
|
||||
[MoveId.ICY_WIND]: RewardTier.GREAT,
|
||||
[MoveId.OUTRAGE]: RewardTier.ULTRA,
|
||||
[MoveId.SANDSTORM]: RewardTier.COMMON,
|
||||
[MoveId.GIGA_DRAIN]: RewardTier.ULTRA,
|
||||
[MoveId.ENDURE]: RewardTier.COMMON,
|
||||
[MoveId.CHARM]: RewardTier.COMMON,
|
||||
[MoveId.FALSE_SWIPE]: RewardTier.COMMON,
|
||||
[MoveId.SWAGGER]: RewardTier.COMMON,
|
||||
[MoveId.STEEL_WING]: RewardTier.GREAT,
|
||||
[MoveId.ATTRACT]: RewardTier.COMMON,
|
||||
[MoveId.SLEEP_TALK]: RewardTier.COMMON,
|
||||
[MoveId.HEAL_BELL]: RewardTier.COMMON,
|
||||
[MoveId.RETURN]: RewardTier.ULTRA,
|
||||
[MoveId.FRUSTRATION]: RewardTier.COMMON,
|
||||
[MoveId.SAFEGUARD]: RewardTier.COMMON,
|
||||
[MoveId.PAIN_SPLIT]: RewardTier.COMMON,
|
||||
[MoveId.MEGAHORN]: RewardTier.ULTRA,
|
||||
[MoveId.BATON_PASS]: RewardTier.COMMON,
|
||||
[MoveId.ENCORE]: RewardTier.COMMON,
|
||||
[MoveId.IRON_TAIL]: RewardTier.GREAT,
|
||||
[MoveId.METAL_CLAW]: RewardTier.COMMON,
|
||||
[MoveId.SYNTHESIS]: RewardTier.GREAT,
|
||||
[MoveId.HIDDEN_POWER]: RewardTier.GREAT,
|
||||
[MoveId.RAIN_DANCE]: RewardTier.COMMON,
|
||||
[MoveId.SUNNY_DAY]: RewardTier.COMMON,
|
||||
[MoveId.CRUNCH]: RewardTier.GREAT,
|
||||
[MoveId.PSYCH_UP]: RewardTier.COMMON,
|
||||
[MoveId.SHADOW_BALL]: RewardTier.ULTRA,
|
||||
[MoveId.FUTURE_SIGHT]: RewardTier.GREAT,
|
||||
[MoveId.ROCK_SMASH]: RewardTier.COMMON,
|
||||
[MoveId.WHIRLPOOL]: RewardTier.COMMON,
|
||||
[MoveId.BEAT_UP]: RewardTier.COMMON,
|
||||
[MoveId.UPROAR]: RewardTier.GREAT,
|
||||
[MoveId.HEAT_WAVE]: RewardTier.ULTRA,
|
||||
[MoveId.HAIL]: RewardTier.COMMON,
|
||||
[MoveId.TORMENT]: RewardTier.COMMON,
|
||||
[MoveId.WILL_O_WISP]: RewardTier.COMMON,
|
||||
[MoveId.FACADE]: RewardTier.GREAT,
|
||||
[MoveId.FOCUS_PUNCH]: RewardTier.COMMON,
|
||||
[MoveId.NATURE_POWER]: RewardTier.COMMON,
|
||||
[MoveId.CHARGE]: RewardTier.COMMON,
|
||||
[MoveId.TAUNT]: RewardTier.COMMON,
|
||||
[MoveId.HELPING_HAND]: RewardTier.COMMON,
|
||||
[MoveId.TRICK]: RewardTier.COMMON,
|
||||
[MoveId.SUPERPOWER]: RewardTier.ULTRA,
|
||||
[MoveId.RECYCLE]: RewardTier.COMMON,
|
||||
[MoveId.REVENGE]: RewardTier.GREAT,
|
||||
[MoveId.BRICK_BREAK]: RewardTier.GREAT,
|
||||
[MoveId.KNOCK_OFF]: RewardTier.GREAT,
|
||||
[MoveId.ENDEAVOR]: RewardTier.COMMON,
|
||||
[MoveId.SKILL_SWAP]: RewardTier.COMMON,
|
||||
[MoveId.IMPRISON]: RewardTier.COMMON,
|
||||
[MoveId.SECRET_POWER]: RewardTier.COMMON,
|
||||
[MoveId.DIVE]: RewardTier.GREAT,
|
||||
[MoveId.FEATHER_DANCE]: RewardTier.COMMON,
|
||||
[MoveId.BLAZE_KICK]: RewardTier.GREAT,
|
||||
[MoveId.HYPER_VOICE]: RewardTier.ULTRA,
|
||||
[MoveId.BLAST_BURN]: RewardTier.ULTRA,
|
||||
[MoveId.HYDRO_CANNON]: RewardTier.ULTRA,
|
||||
[MoveId.WEATHER_BALL]: RewardTier.COMMON,
|
||||
[MoveId.FAKE_TEARS]: RewardTier.COMMON,
|
||||
[MoveId.AIR_CUTTER]: RewardTier.GREAT,
|
||||
[MoveId.OVERHEAT]: RewardTier.ULTRA,
|
||||
[MoveId.ROCK_TOMB]: RewardTier.GREAT,
|
||||
[MoveId.METAL_SOUND]: RewardTier.COMMON,
|
||||
[MoveId.COSMIC_POWER]: RewardTier.COMMON,
|
||||
[MoveId.SIGNAL_BEAM]: RewardTier.GREAT,
|
||||
[MoveId.SAND_TOMB]: RewardTier.COMMON,
|
||||
[MoveId.MUDDY_WATER]: RewardTier.GREAT,
|
||||
[MoveId.BULLET_SEED]: RewardTier.GREAT,
|
||||
[MoveId.AERIAL_ACE]: RewardTier.GREAT,
|
||||
[MoveId.ICICLE_SPEAR]: RewardTier.GREAT,
|
||||
[MoveId.IRON_DEFENSE]: RewardTier.GREAT,
|
||||
[MoveId.DRAGON_CLAW]: RewardTier.ULTRA,
|
||||
[MoveId.FRENZY_PLANT]: RewardTier.ULTRA,
|
||||
[MoveId.BULK_UP]: RewardTier.COMMON,
|
||||
[MoveId.BOUNCE]: RewardTier.GREAT,
|
||||
[MoveId.MUD_SHOT]: RewardTier.GREAT,
|
||||
[MoveId.POISON_TAIL]: RewardTier.GREAT,
|
||||
[MoveId.COVET]: RewardTier.GREAT,
|
||||
[MoveId.MAGICAL_LEAF]: RewardTier.GREAT,
|
||||
[MoveId.CALM_MIND]: RewardTier.GREAT,
|
||||
[MoveId.LEAF_BLADE]: RewardTier.ULTRA,
|
||||
[MoveId.DRAGON_DANCE]: RewardTier.GREAT,
|
||||
[MoveId.ROCK_BLAST]: RewardTier.GREAT,
|
||||
[MoveId.WATER_PULSE]: RewardTier.GREAT,
|
||||
[MoveId.ROOST]: RewardTier.GREAT,
|
||||
[MoveId.GRAVITY]: RewardTier.COMMON,
|
||||
[MoveId.GYRO_BALL]: RewardTier.COMMON,
|
||||
[MoveId.BRINE]: RewardTier.GREAT,
|
||||
[MoveId.PLUCK]: RewardTier.GREAT,
|
||||
[MoveId.TAILWIND]: RewardTier.GREAT,
|
||||
[MoveId.U_TURN]: RewardTier.GREAT,
|
||||
[MoveId.CLOSE_COMBAT]: RewardTier.ULTRA,
|
||||
[MoveId.PAYBACK]: RewardTier.COMMON,
|
||||
[MoveId.ASSURANCE]: RewardTier.COMMON,
|
||||
[MoveId.EMBARGO]: RewardTier.COMMON,
|
||||
[MoveId.FLING]: RewardTier.COMMON,
|
||||
[MoveId.GASTRO_ACID]: RewardTier.GREAT,
|
||||
[MoveId.POWER_SWAP]: RewardTier.COMMON,
|
||||
[MoveId.GUARD_SWAP]: RewardTier.COMMON,
|
||||
[MoveId.WORRY_SEED]: RewardTier.GREAT,
|
||||
[MoveId.TOXIC_SPIKES]: RewardTier.GREAT,
|
||||
[MoveId.FLARE_BLITZ]: RewardTier.ULTRA,
|
||||
[MoveId.AURA_SPHERE]: RewardTier.GREAT,
|
||||
[MoveId.ROCK_POLISH]: RewardTier.COMMON,
|
||||
[MoveId.POISON_JAB]: RewardTier.GREAT,
|
||||
[MoveId.DARK_PULSE]: RewardTier.GREAT,
|
||||
[MoveId.AQUA_TAIL]: RewardTier.GREAT,
|
||||
[MoveId.SEED_BOMB]: RewardTier.GREAT,
|
||||
[MoveId.AIR_SLASH]: RewardTier.GREAT,
|
||||
[MoveId.X_SCISSOR]: RewardTier.GREAT,
|
||||
[MoveId.BUG_BUZZ]: RewardTier.GREAT,
|
||||
[MoveId.DRAGON_PULSE]: RewardTier.GREAT,
|
||||
[MoveId.POWER_GEM]: RewardTier.GREAT,
|
||||
[MoveId.DRAIN_PUNCH]: RewardTier.GREAT,
|
||||
[MoveId.VACUUM_WAVE]: RewardTier.COMMON,
|
||||
[MoveId.FOCUS_BLAST]: RewardTier.GREAT,
|
||||
[MoveId.ENERGY_BALL]: RewardTier.GREAT,
|
||||
[MoveId.BRAVE_BIRD]: RewardTier.ULTRA,
|
||||
[MoveId.EARTH_POWER]: RewardTier.ULTRA,
|
||||
[MoveId.GIGA_IMPACT]: RewardTier.GREAT,
|
||||
[MoveId.NASTY_PLOT]: RewardTier.COMMON,
|
||||
[MoveId.AVALANCHE]: RewardTier.GREAT,
|
||||
[MoveId.SHADOW_CLAW]: RewardTier.GREAT,
|
||||
[MoveId.THUNDER_FANG]: RewardTier.GREAT,
|
||||
[MoveId.ICE_FANG]: RewardTier.GREAT,
|
||||
[MoveId.FIRE_FANG]: RewardTier.GREAT,
|
||||
[MoveId.PSYCHO_CUT]: RewardTier.GREAT,
|
||||
[MoveId.ZEN_HEADBUTT]: RewardTier.GREAT,
|
||||
[MoveId.FLASH_CANNON]: RewardTier.GREAT,
|
||||
[MoveId.ROCK_CLIMB]: RewardTier.GREAT,
|
||||
[MoveId.DEFOG]: RewardTier.COMMON,
|
||||
[MoveId.TRICK_ROOM]: RewardTier.COMMON,
|
||||
[MoveId.DRACO_METEOR]: RewardTier.ULTRA,
|
||||
[MoveId.LEAF_STORM]: RewardTier.ULTRA,
|
||||
[MoveId.POWER_WHIP]: RewardTier.ULTRA,
|
||||
[MoveId.CROSS_POISON]: RewardTier.GREAT,
|
||||
[MoveId.GUNK_SHOT]: RewardTier.ULTRA,
|
||||
[MoveId.IRON_HEAD]: RewardTier.GREAT,
|
||||
[MoveId.STONE_EDGE]: RewardTier.ULTRA,
|
||||
[MoveId.STEALTH_ROCK]: RewardTier.COMMON,
|
||||
[MoveId.GRASS_KNOT]: RewardTier.ULTRA,
|
||||
[MoveId.BUG_BITE]: RewardTier.GREAT,
|
||||
[MoveId.CHARGE_BEAM]: RewardTier.GREAT,
|
||||
[MoveId.HONE_CLAWS]: RewardTier.COMMON,
|
||||
[MoveId.WONDER_ROOM]: RewardTier.COMMON,
|
||||
[MoveId.PSYSHOCK]: RewardTier.GREAT,
|
||||
[MoveId.VENOSHOCK]: RewardTier.GREAT,
|
||||
[MoveId.MAGIC_ROOM]: RewardTier.COMMON,
|
||||
[MoveId.SMACK_DOWN]: RewardTier.COMMON,
|
||||
[MoveId.SLUDGE_WAVE]: RewardTier.GREAT,
|
||||
[MoveId.HEAVY_SLAM]: RewardTier.GREAT,
|
||||
[MoveId.ELECTRO_BALL]: RewardTier.GREAT,
|
||||
[MoveId.FLAME_CHARGE]: RewardTier.GREAT,
|
||||
[MoveId.LOW_SWEEP]: RewardTier.GREAT,
|
||||
[MoveId.ACID_SPRAY]: RewardTier.COMMON,
|
||||
[MoveId.FOUL_PLAY]: RewardTier.ULTRA,
|
||||
[MoveId.ROUND]: RewardTier.COMMON,
|
||||
[MoveId.ECHOED_VOICE]: RewardTier.COMMON,
|
||||
[MoveId.STORED_POWER]: RewardTier.COMMON,
|
||||
[MoveId.ALLY_SWITCH]: RewardTier.COMMON,
|
||||
[MoveId.SCALD]: RewardTier.GREAT,
|
||||
[MoveId.HEX]: RewardTier.GREAT,
|
||||
[MoveId.SKY_DROP]: RewardTier.GREAT,
|
||||
[MoveId.INCINERATE]: RewardTier.GREAT,
|
||||
[MoveId.QUASH]: RewardTier.COMMON,
|
||||
[MoveId.ACROBATICS]: RewardTier.GREAT,
|
||||
[MoveId.RETALIATE]: RewardTier.GREAT,
|
||||
[MoveId.WATER_PLEDGE]: RewardTier.GREAT,
|
||||
[MoveId.FIRE_PLEDGE]: RewardTier.GREAT,
|
||||
[MoveId.GRASS_PLEDGE]: RewardTier.GREAT,
|
||||
[MoveId.VOLT_SWITCH]: RewardTier.GREAT,
|
||||
[MoveId.STRUGGLE_BUG]: RewardTier.COMMON,
|
||||
[MoveId.BULLDOZE]: RewardTier.GREAT,
|
||||
[MoveId.FROST_BREATH]: RewardTier.GREAT,
|
||||
[MoveId.DRAGON_TAIL]: RewardTier.GREAT,
|
||||
[MoveId.WORK_UP]: RewardTier.COMMON,
|
||||
[MoveId.ELECTROWEB]: RewardTier.GREAT,
|
||||
[MoveId.WILD_CHARGE]: RewardTier.GREAT,
|
||||
[MoveId.DRILL_RUN]: RewardTier.GREAT,
|
||||
[MoveId.RAZOR_SHELL]: RewardTier.GREAT,
|
||||
[MoveId.HEAT_CRASH]: RewardTier.GREAT,
|
||||
[MoveId.TAIL_SLAP]: RewardTier.GREAT,
|
||||
[MoveId.HURRICANE]: RewardTier.ULTRA,
|
||||
[MoveId.SNARL]: RewardTier.COMMON,
|
||||
[MoveId.PHANTOM_FORCE]: RewardTier.ULTRA,
|
||||
[MoveId.PETAL_BLIZZARD]: RewardTier.GREAT,
|
||||
[MoveId.DISARMING_VOICE]: RewardTier.GREAT,
|
||||
[MoveId.DRAINING_KISS]: RewardTier.GREAT,
|
||||
[MoveId.GRASSY_TERRAIN]: RewardTier.COMMON,
|
||||
[MoveId.MISTY_TERRAIN]: RewardTier.COMMON,
|
||||
[MoveId.PLAY_ROUGH]: RewardTier.GREAT,
|
||||
[MoveId.CONFIDE]: RewardTier.COMMON,
|
||||
[MoveId.MYSTICAL_FIRE]: RewardTier.GREAT,
|
||||
[MoveId.EERIE_IMPULSE]: RewardTier.COMMON,
|
||||
[MoveId.VENOM_DRENCH]: RewardTier.COMMON,
|
||||
[MoveId.ELECTRIC_TERRAIN]: RewardTier.COMMON,
|
||||
[MoveId.DAZZLING_GLEAM]: RewardTier.ULTRA,
|
||||
[MoveId.INFESTATION]: RewardTier.COMMON,
|
||||
[MoveId.POWER_UP_PUNCH]: RewardTier.GREAT,
|
||||
[MoveId.DARKEST_LARIAT]: RewardTier.GREAT,
|
||||
[MoveId.HIGH_HORSEPOWER]: RewardTier.ULTRA,
|
||||
[MoveId.SOLAR_BLADE]: RewardTier.GREAT,
|
||||
[MoveId.THROAT_CHOP]: RewardTier.GREAT,
|
||||
[MoveId.POLLEN_PUFF]: RewardTier.GREAT,
|
||||
[MoveId.PSYCHIC_TERRAIN]: RewardTier.COMMON,
|
||||
[MoveId.LUNGE]: RewardTier.GREAT,
|
||||
[MoveId.SPEED_SWAP]: RewardTier.COMMON,
|
||||
[MoveId.SMART_STRIKE]: RewardTier.GREAT,
|
||||
[MoveId.BRUTAL_SWING]: RewardTier.GREAT,
|
||||
[MoveId.AURORA_VEIL]: RewardTier.COMMON,
|
||||
[MoveId.PSYCHIC_FANGS]: RewardTier.GREAT,
|
||||
[MoveId.STOMPING_TANTRUM]: RewardTier.GREAT,
|
||||
[MoveId.LIQUIDATION]: RewardTier.ULTRA,
|
||||
[MoveId.BODY_PRESS]: RewardTier.ULTRA,
|
||||
[MoveId.BREAKING_SWIPE]: RewardTier.GREAT,
|
||||
[MoveId.STEEL_BEAM]: RewardTier.ULTRA,
|
||||
[MoveId.EXPANDING_FORCE]: RewardTier.GREAT,
|
||||
[MoveId.STEEL_ROLLER]: RewardTier.COMMON,
|
||||
[MoveId.SCALE_SHOT]: RewardTier.ULTRA,
|
||||
[MoveId.METEOR_BEAM]: RewardTier.GREAT,
|
||||
[MoveId.MISTY_EXPLOSION]: RewardTier.COMMON,
|
||||
[MoveId.GRASSY_GLIDE]: RewardTier.COMMON,
|
||||
[MoveId.RISING_VOLTAGE]: RewardTier.COMMON,
|
||||
[MoveId.TERRAIN_PULSE]: RewardTier.COMMON,
|
||||
[MoveId.SKITTER_SMACK]: RewardTier.GREAT,
|
||||
[MoveId.BURNING_JEALOUSY]: RewardTier.GREAT,
|
||||
[MoveId.LASH_OUT]: RewardTier.GREAT,
|
||||
[MoveId.POLTERGEIST]: RewardTier.ULTRA,
|
||||
[MoveId.CORROSIVE_GAS]: RewardTier.COMMON,
|
||||
[MoveId.COACHING]: RewardTier.COMMON,
|
||||
[MoveId.FLIP_TURN]: RewardTier.COMMON,
|
||||
[MoveId.TRIPLE_AXEL]: RewardTier.COMMON,
|
||||
[MoveId.DUAL_WINGBEAT]: RewardTier.COMMON,
|
||||
[MoveId.SCORCHING_SANDS]: RewardTier.GREAT,
|
||||
[MoveId.TERA_BLAST]: RewardTier.GREAT,
|
||||
[MoveId.ICE_SPINNER]: RewardTier.GREAT,
|
||||
[MoveId.SNOWSCAPE]: RewardTier.COMMON,
|
||||
[MoveId.POUNCE]: RewardTier.COMMON,
|
||||
[MoveId.TRAILBLAZE]: RewardTier.COMMON,
|
||||
[MoveId.CHILLING_WATER]: RewardTier.COMMON,
|
||||
[MoveId.HARD_PRESS]: RewardTier.GREAT,
|
||||
[MoveId.DRAGON_CHEER]: RewardTier.COMMON,
|
||||
[MoveId.ALLURING_VOICE]: RewardTier.GREAT,
|
||||
[MoveId.TEMPER_FLARE]: RewardTier.GREAT,
|
||||
[MoveId.SUPERCELL_SLAM]: RewardTier.GREAT,
|
||||
[MoveId.PSYCHIC_NOISE]: RewardTier.GREAT,
|
||||
[MoveId.UPPER_HAND]: RewardTier.COMMON,
|
||||
[MoveId.MEGA_PUNCH]: RarityTier.GREAT,
|
||||
[MoveId.PAY_DAY]: RarityTier.ULTRA,
|
||||
[MoveId.FIRE_PUNCH]: RarityTier.GREAT,
|
||||
[MoveId.ICE_PUNCH]: RarityTier.GREAT,
|
||||
[MoveId.THUNDER_PUNCH]: RarityTier.GREAT,
|
||||
[MoveId.SWORDS_DANCE]: RarityTier.COMMON,
|
||||
[MoveId.CUT]: RarityTier.COMMON,
|
||||
[MoveId.FLY]: RarityTier.COMMON,
|
||||
[MoveId.MEGA_KICK]: RarityTier.GREAT,
|
||||
[MoveId.BODY_SLAM]: RarityTier.GREAT,
|
||||
[MoveId.TAKE_DOWN]: RarityTier.GREAT,
|
||||
[MoveId.DOUBLE_EDGE]: RarityTier.ULTRA,
|
||||
[MoveId.PIN_MISSILE]: RarityTier.COMMON,
|
||||
[MoveId.ROAR]: RarityTier.COMMON,
|
||||
[MoveId.FLAMETHROWER]: RarityTier.ULTRA,
|
||||
[MoveId.HYDRO_PUMP]: RarityTier.ULTRA,
|
||||
[MoveId.SURF]: RarityTier.ULTRA,
|
||||
[MoveId.ICE_BEAM]: RarityTier.ULTRA,
|
||||
[MoveId.BLIZZARD]: RarityTier.ULTRA,
|
||||
[MoveId.PSYBEAM]: RarityTier.GREAT,
|
||||
[MoveId.HYPER_BEAM]: RarityTier.ULTRA,
|
||||
[MoveId.LOW_KICK]: RarityTier.COMMON,
|
||||
[MoveId.COUNTER]: RarityTier.COMMON,
|
||||
[MoveId.STRENGTH]: RarityTier.GREAT,
|
||||
[MoveId.SOLAR_BEAM]: RarityTier.ULTRA,
|
||||
[MoveId.FIRE_SPIN]: RarityTier.COMMON,
|
||||
[MoveId.THUNDERBOLT]: RarityTier.ULTRA,
|
||||
[MoveId.THUNDER_WAVE]: RarityTier.COMMON,
|
||||
[MoveId.THUNDER]: RarityTier.ULTRA,
|
||||
[MoveId.EARTHQUAKE]: RarityTier.ULTRA,
|
||||
[MoveId.DIG]: RarityTier.GREAT,
|
||||
[MoveId.TOXIC]: RarityTier.GREAT,
|
||||
[MoveId.PSYCHIC]: RarityTier.ULTRA,
|
||||
[MoveId.AGILITY]: RarityTier.COMMON,
|
||||
[MoveId.NIGHT_SHADE]: RarityTier.COMMON,
|
||||
[MoveId.SCREECH]: RarityTier.COMMON,
|
||||
[MoveId.DOUBLE_TEAM]: RarityTier.COMMON,
|
||||
[MoveId.CONFUSE_RAY]: RarityTier.COMMON,
|
||||
[MoveId.LIGHT_SCREEN]: RarityTier.COMMON,
|
||||
[MoveId.HAZE]: RarityTier.COMMON,
|
||||
[MoveId.REFLECT]: RarityTier.COMMON,
|
||||
[MoveId.FOCUS_ENERGY]: RarityTier.COMMON,
|
||||
[MoveId.METRONOME]: RarityTier.COMMON,
|
||||
[MoveId.SELF_DESTRUCT]: RarityTier.GREAT,
|
||||
[MoveId.FIRE_BLAST]: RarityTier.ULTRA,
|
||||
[MoveId.WATERFALL]: RarityTier.GREAT,
|
||||
[MoveId.SWIFT]: RarityTier.COMMON,
|
||||
[MoveId.AMNESIA]: RarityTier.COMMON,
|
||||
[MoveId.DREAM_EATER]: RarityTier.GREAT,
|
||||
[MoveId.LEECH_LIFE]: RarityTier.ULTRA,
|
||||
[MoveId.FLASH]: RarityTier.COMMON,
|
||||
[MoveId.EXPLOSION]: RarityTier.GREAT,
|
||||
[MoveId.REST]: RarityTier.COMMON,
|
||||
[MoveId.ROCK_SLIDE]: RarityTier.GREAT,
|
||||
[MoveId.TRI_ATTACK]: RarityTier.ULTRA,
|
||||
[MoveId.SUPER_FANG]: RarityTier.COMMON,
|
||||
[MoveId.SUBSTITUTE]: RarityTier.COMMON,
|
||||
[MoveId.THIEF]: RarityTier.GREAT,
|
||||
[MoveId.SNORE]: RarityTier.COMMON,
|
||||
[MoveId.CURSE]: RarityTier.COMMON,
|
||||
[MoveId.REVERSAL]: RarityTier.COMMON,
|
||||
[MoveId.SPITE]: RarityTier.COMMON,
|
||||
[MoveId.PROTECT]: RarityTier.COMMON,
|
||||
[MoveId.SCARY_FACE]: RarityTier.COMMON,
|
||||
[MoveId.SLUDGE_BOMB]: RarityTier.GREAT,
|
||||
[MoveId.MUD_SLAP]: RarityTier.COMMON,
|
||||
[MoveId.SPIKES]: RarityTier.COMMON,
|
||||
[MoveId.ICY_WIND]: RarityTier.GREAT,
|
||||
[MoveId.OUTRAGE]: RarityTier.ULTRA,
|
||||
[MoveId.SANDSTORM]: RarityTier.COMMON,
|
||||
[MoveId.GIGA_DRAIN]: RarityTier.ULTRA,
|
||||
[MoveId.ENDURE]: RarityTier.COMMON,
|
||||
[MoveId.CHARM]: RarityTier.COMMON,
|
||||
[MoveId.FALSE_SWIPE]: RarityTier.COMMON,
|
||||
[MoveId.SWAGGER]: RarityTier.COMMON,
|
||||
[MoveId.STEEL_WING]: RarityTier.GREAT,
|
||||
[MoveId.ATTRACT]: RarityTier.COMMON,
|
||||
[MoveId.SLEEP_TALK]: RarityTier.COMMON,
|
||||
[MoveId.HEAL_BELL]: RarityTier.COMMON,
|
||||
[MoveId.RETURN]: RarityTier.ULTRA,
|
||||
[MoveId.FRUSTRATION]: RarityTier.COMMON,
|
||||
[MoveId.SAFEGUARD]: RarityTier.COMMON,
|
||||
[MoveId.PAIN_SPLIT]: RarityTier.COMMON,
|
||||
[MoveId.MEGAHORN]: RarityTier.ULTRA,
|
||||
[MoveId.BATON_PASS]: RarityTier.COMMON,
|
||||
[MoveId.ENCORE]: RarityTier.COMMON,
|
||||
[MoveId.IRON_TAIL]: RarityTier.GREAT,
|
||||
[MoveId.METAL_CLAW]: RarityTier.COMMON,
|
||||
[MoveId.SYNTHESIS]: RarityTier.GREAT,
|
||||
[MoveId.HIDDEN_POWER]: RarityTier.GREAT,
|
||||
[MoveId.RAIN_DANCE]: RarityTier.COMMON,
|
||||
[MoveId.SUNNY_DAY]: RarityTier.COMMON,
|
||||
[MoveId.CRUNCH]: RarityTier.GREAT,
|
||||
[MoveId.PSYCH_UP]: RarityTier.COMMON,
|
||||
[MoveId.SHADOW_BALL]: RarityTier.ULTRA,
|
||||
[MoveId.FUTURE_SIGHT]: RarityTier.GREAT,
|
||||
[MoveId.ROCK_SMASH]: RarityTier.COMMON,
|
||||
[MoveId.WHIRLPOOL]: RarityTier.COMMON,
|
||||
[MoveId.BEAT_UP]: RarityTier.COMMON,
|
||||
[MoveId.UPROAR]: RarityTier.GREAT,
|
||||
[MoveId.HEAT_WAVE]: RarityTier.ULTRA,
|
||||
[MoveId.HAIL]: RarityTier.COMMON,
|
||||
[MoveId.TORMENT]: RarityTier.COMMON,
|
||||
[MoveId.WILL_O_WISP]: RarityTier.COMMON,
|
||||
[MoveId.FACADE]: RarityTier.GREAT,
|
||||
[MoveId.FOCUS_PUNCH]: RarityTier.COMMON,
|
||||
[MoveId.NATURE_POWER]: RarityTier.COMMON,
|
||||
[MoveId.CHARGE]: RarityTier.COMMON,
|
||||
[MoveId.TAUNT]: RarityTier.COMMON,
|
||||
[MoveId.HELPING_HAND]: RarityTier.COMMON,
|
||||
[MoveId.TRICK]: RarityTier.COMMON,
|
||||
[MoveId.SUPERPOWER]: RarityTier.ULTRA,
|
||||
[MoveId.RECYCLE]: RarityTier.COMMON,
|
||||
[MoveId.REVENGE]: RarityTier.GREAT,
|
||||
[MoveId.BRICK_BREAK]: RarityTier.GREAT,
|
||||
[MoveId.KNOCK_OFF]: RarityTier.GREAT,
|
||||
[MoveId.ENDEAVOR]: RarityTier.COMMON,
|
||||
[MoveId.SKILL_SWAP]: RarityTier.COMMON,
|
||||
[MoveId.IMPRISON]: RarityTier.COMMON,
|
||||
[MoveId.SECRET_POWER]: RarityTier.COMMON,
|
||||
[MoveId.DIVE]: RarityTier.GREAT,
|
||||
[MoveId.FEATHER_DANCE]: RarityTier.COMMON,
|
||||
[MoveId.BLAZE_KICK]: RarityTier.GREAT,
|
||||
[MoveId.HYPER_VOICE]: RarityTier.ULTRA,
|
||||
[MoveId.BLAST_BURN]: RarityTier.ULTRA,
|
||||
[MoveId.HYDRO_CANNON]: RarityTier.ULTRA,
|
||||
[MoveId.WEATHER_BALL]: RarityTier.COMMON,
|
||||
[MoveId.FAKE_TEARS]: RarityTier.COMMON,
|
||||
[MoveId.AIR_CUTTER]: RarityTier.GREAT,
|
||||
[MoveId.OVERHEAT]: RarityTier.ULTRA,
|
||||
[MoveId.ROCK_TOMB]: RarityTier.GREAT,
|
||||
[MoveId.METAL_SOUND]: RarityTier.COMMON,
|
||||
[MoveId.COSMIC_POWER]: RarityTier.COMMON,
|
||||
[MoveId.SIGNAL_BEAM]: RarityTier.GREAT,
|
||||
[MoveId.SAND_TOMB]: RarityTier.COMMON,
|
||||
[MoveId.MUDDY_WATER]: RarityTier.GREAT,
|
||||
[MoveId.BULLET_SEED]: RarityTier.GREAT,
|
||||
[MoveId.AERIAL_ACE]: RarityTier.GREAT,
|
||||
[MoveId.ICICLE_SPEAR]: RarityTier.GREAT,
|
||||
[MoveId.IRON_DEFENSE]: RarityTier.GREAT,
|
||||
[MoveId.DRAGON_CLAW]: RarityTier.ULTRA,
|
||||
[MoveId.FRENZY_PLANT]: RarityTier.ULTRA,
|
||||
[MoveId.BULK_UP]: RarityTier.COMMON,
|
||||
[MoveId.BOUNCE]: RarityTier.GREAT,
|
||||
[MoveId.MUD_SHOT]: RarityTier.GREAT,
|
||||
[MoveId.POISON_TAIL]: RarityTier.GREAT,
|
||||
[MoveId.COVET]: RarityTier.GREAT,
|
||||
[MoveId.MAGICAL_LEAF]: RarityTier.GREAT,
|
||||
[MoveId.CALM_MIND]: RarityTier.GREAT,
|
||||
[MoveId.LEAF_BLADE]: RarityTier.ULTRA,
|
||||
[MoveId.DRAGON_DANCE]: RarityTier.GREAT,
|
||||
[MoveId.ROCK_BLAST]: RarityTier.GREAT,
|
||||
[MoveId.WATER_PULSE]: RarityTier.GREAT,
|
||||
[MoveId.ROOST]: RarityTier.GREAT,
|
||||
[MoveId.GRAVITY]: RarityTier.COMMON,
|
||||
[MoveId.GYRO_BALL]: RarityTier.COMMON,
|
||||
[MoveId.BRINE]: RarityTier.GREAT,
|
||||
[MoveId.PLUCK]: RarityTier.GREAT,
|
||||
[MoveId.TAILWIND]: RarityTier.GREAT,
|
||||
[MoveId.U_TURN]: RarityTier.GREAT,
|
||||
[MoveId.CLOSE_COMBAT]: RarityTier.ULTRA,
|
||||
[MoveId.PAYBACK]: RarityTier.COMMON,
|
||||
[MoveId.ASSURANCE]: RarityTier.COMMON,
|
||||
[MoveId.EMBARGO]: RarityTier.COMMON,
|
||||
[MoveId.FLING]: RarityTier.COMMON,
|
||||
[MoveId.GASTRO_ACID]: RarityTier.GREAT,
|
||||
[MoveId.POWER_SWAP]: RarityTier.COMMON,
|
||||
[MoveId.GUARD_SWAP]: RarityTier.COMMON,
|
||||
[MoveId.WORRY_SEED]: RarityTier.GREAT,
|
||||
[MoveId.TOXIC_SPIKES]: RarityTier.GREAT,
|
||||
[MoveId.FLARE_BLITZ]: RarityTier.ULTRA,
|
||||
[MoveId.AURA_SPHERE]: RarityTier.GREAT,
|
||||
[MoveId.ROCK_POLISH]: RarityTier.COMMON,
|
||||
[MoveId.POISON_JAB]: RarityTier.GREAT,
|
||||
[MoveId.DARK_PULSE]: RarityTier.GREAT,
|
||||
[MoveId.AQUA_TAIL]: RarityTier.GREAT,
|
||||
[MoveId.SEED_BOMB]: RarityTier.GREAT,
|
||||
[MoveId.AIR_SLASH]: RarityTier.GREAT,
|
||||
[MoveId.X_SCISSOR]: RarityTier.GREAT,
|
||||
[MoveId.BUG_BUZZ]: RarityTier.GREAT,
|
||||
[MoveId.DRAGON_PULSE]: RarityTier.GREAT,
|
||||
[MoveId.POWER_GEM]: RarityTier.GREAT,
|
||||
[MoveId.DRAIN_PUNCH]: RarityTier.GREAT,
|
||||
[MoveId.VACUUM_WAVE]: RarityTier.COMMON,
|
||||
[MoveId.FOCUS_BLAST]: RarityTier.GREAT,
|
||||
[MoveId.ENERGY_BALL]: RarityTier.GREAT,
|
||||
[MoveId.BRAVE_BIRD]: RarityTier.ULTRA,
|
||||
[MoveId.EARTH_POWER]: RarityTier.ULTRA,
|
||||
[MoveId.GIGA_IMPACT]: RarityTier.GREAT,
|
||||
[MoveId.NASTY_PLOT]: RarityTier.COMMON,
|
||||
[MoveId.AVALANCHE]: RarityTier.GREAT,
|
||||
[MoveId.SHADOW_CLAW]: RarityTier.GREAT,
|
||||
[MoveId.THUNDER_FANG]: RarityTier.GREAT,
|
||||
[MoveId.ICE_FANG]: RarityTier.GREAT,
|
||||
[MoveId.FIRE_FANG]: RarityTier.GREAT,
|
||||
[MoveId.PSYCHO_CUT]: RarityTier.GREAT,
|
||||
[MoveId.ZEN_HEADBUTT]: RarityTier.GREAT,
|
||||
[MoveId.FLASH_CANNON]: RarityTier.GREAT,
|
||||
[MoveId.ROCK_CLIMB]: RarityTier.GREAT,
|
||||
[MoveId.DEFOG]: RarityTier.COMMON,
|
||||
[MoveId.TRICK_ROOM]: RarityTier.COMMON,
|
||||
[MoveId.DRACO_METEOR]: RarityTier.ULTRA,
|
||||
[MoveId.LEAF_STORM]: RarityTier.ULTRA,
|
||||
[MoveId.POWER_WHIP]: RarityTier.ULTRA,
|
||||
[MoveId.CROSS_POISON]: RarityTier.GREAT,
|
||||
[MoveId.GUNK_SHOT]: RarityTier.ULTRA,
|
||||
[MoveId.IRON_HEAD]: RarityTier.GREAT,
|
||||
[MoveId.STONE_EDGE]: RarityTier.ULTRA,
|
||||
[MoveId.STEALTH_ROCK]: RarityTier.COMMON,
|
||||
[MoveId.GRASS_KNOT]: RarityTier.ULTRA,
|
||||
[MoveId.BUG_BITE]: RarityTier.GREAT,
|
||||
[MoveId.CHARGE_BEAM]: RarityTier.GREAT,
|
||||
[MoveId.HONE_CLAWS]: RarityTier.COMMON,
|
||||
[MoveId.WONDER_ROOM]: RarityTier.COMMON,
|
||||
[MoveId.PSYSHOCK]: RarityTier.GREAT,
|
||||
[MoveId.VENOSHOCK]: RarityTier.GREAT,
|
||||
[MoveId.MAGIC_ROOM]: RarityTier.COMMON,
|
||||
[MoveId.SMACK_DOWN]: RarityTier.COMMON,
|
||||
[MoveId.SLUDGE_WAVE]: RarityTier.GREAT,
|
||||
[MoveId.HEAVY_SLAM]: RarityTier.GREAT,
|
||||
[MoveId.ELECTRO_BALL]: RarityTier.GREAT,
|
||||
[MoveId.FLAME_CHARGE]: RarityTier.GREAT,
|
||||
[MoveId.LOW_SWEEP]: RarityTier.GREAT,
|
||||
[MoveId.ACID_SPRAY]: RarityTier.COMMON,
|
||||
[MoveId.FOUL_PLAY]: RarityTier.ULTRA,
|
||||
[MoveId.ROUND]: RarityTier.COMMON,
|
||||
[MoveId.ECHOED_VOICE]: RarityTier.COMMON,
|
||||
[MoveId.STORED_POWER]: RarityTier.COMMON,
|
||||
[MoveId.ALLY_SWITCH]: RarityTier.COMMON,
|
||||
[MoveId.SCALD]: RarityTier.GREAT,
|
||||
[MoveId.HEX]: RarityTier.GREAT,
|
||||
[MoveId.SKY_DROP]: RarityTier.GREAT,
|
||||
[MoveId.INCINERATE]: RarityTier.GREAT,
|
||||
[MoveId.QUASH]: RarityTier.COMMON,
|
||||
[MoveId.ACROBATICS]: RarityTier.GREAT,
|
||||
[MoveId.RETALIATE]: RarityTier.GREAT,
|
||||
[MoveId.WATER_PLEDGE]: RarityTier.GREAT,
|
||||
[MoveId.FIRE_PLEDGE]: RarityTier.GREAT,
|
||||
[MoveId.GRASS_PLEDGE]: RarityTier.GREAT,
|
||||
[MoveId.VOLT_SWITCH]: RarityTier.GREAT,
|
||||
[MoveId.STRUGGLE_BUG]: RarityTier.COMMON,
|
||||
[MoveId.BULLDOZE]: RarityTier.GREAT,
|
||||
[MoveId.FROST_BREATH]: RarityTier.GREAT,
|
||||
[MoveId.DRAGON_TAIL]: RarityTier.GREAT,
|
||||
[MoveId.WORK_UP]: RarityTier.COMMON,
|
||||
[MoveId.ELECTROWEB]: RarityTier.GREAT,
|
||||
[MoveId.WILD_CHARGE]: RarityTier.GREAT,
|
||||
[MoveId.DRILL_RUN]: RarityTier.GREAT,
|
||||
[MoveId.RAZOR_SHELL]: RarityTier.GREAT,
|
||||
[MoveId.HEAT_CRASH]: RarityTier.GREAT,
|
||||
[MoveId.TAIL_SLAP]: RarityTier.GREAT,
|
||||
[MoveId.HURRICANE]: RarityTier.ULTRA,
|
||||
[MoveId.SNARL]: RarityTier.COMMON,
|
||||
[MoveId.PHANTOM_FORCE]: RarityTier.ULTRA,
|
||||
[MoveId.PETAL_BLIZZARD]: RarityTier.GREAT,
|
||||
[MoveId.DISARMING_VOICE]: RarityTier.GREAT,
|
||||
[MoveId.DRAINING_KISS]: RarityTier.GREAT,
|
||||
[MoveId.GRASSY_TERRAIN]: RarityTier.COMMON,
|
||||
[MoveId.MISTY_TERRAIN]: RarityTier.COMMON,
|
||||
[MoveId.PLAY_ROUGH]: RarityTier.GREAT,
|
||||
[MoveId.CONFIDE]: RarityTier.COMMON,
|
||||
[MoveId.MYSTICAL_FIRE]: RarityTier.GREAT,
|
||||
[MoveId.EERIE_IMPULSE]: RarityTier.COMMON,
|
||||
[MoveId.VENOM_DRENCH]: RarityTier.COMMON,
|
||||
[MoveId.ELECTRIC_TERRAIN]: RarityTier.COMMON,
|
||||
[MoveId.DAZZLING_GLEAM]: RarityTier.ULTRA,
|
||||
[MoveId.INFESTATION]: RarityTier.COMMON,
|
||||
[MoveId.POWER_UP_PUNCH]: RarityTier.GREAT,
|
||||
[MoveId.DARKEST_LARIAT]: RarityTier.GREAT,
|
||||
[MoveId.HIGH_HORSEPOWER]: RarityTier.ULTRA,
|
||||
[MoveId.SOLAR_BLADE]: RarityTier.GREAT,
|
||||
[MoveId.THROAT_CHOP]: RarityTier.GREAT,
|
||||
[MoveId.POLLEN_PUFF]: RarityTier.GREAT,
|
||||
[MoveId.PSYCHIC_TERRAIN]: RarityTier.COMMON,
|
||||
[MoveId.LUNGE]: RarityTier.GREAT,
|
||||
[MoveId.SPEED_SWAP]: RarityTier.COMMON,
|
||||
[MoveId.SMART_STRIKE]: RarityTier.GREAT,
|
||||
[MoveId.BRUTAL_SWING]: RarityTier.GREAT,
|
||||
[MoveId.AURORA_VEIL]: RarityTier.COMMON,
|
||||
[MoveId.PSYCHIC_FANGS]: RarityTier.GREAT,
|
||||
[MoveId.STOMPING_TANTRUM]: RarityTier.GREAT,
|
||||
[MoveId.LIQUIDATION]: RarityTier.ULTRA,
|
||||
[MoveId.BODY_PRESS]: RarityTier.ULTRA,
|
||||
[MoveId.BREAKING_SWIPE]: RarityTier.GREAT,
|
||||
[MoveId.STEEL_BEAM]: RarityTier.ULTRA,
|
||||
[MoveId.EXPANDING_FORCE]: RarityTier.GREAT,
|
||||
[MoveId.STEEL_ROLLER]: RarityTier.COMMON,
|
||||
[MoveId.SCALE_SHOT]: RarityTier.ULTRA,
|
||||
[MoveId.METEOR_BEAM]: RarityTier.GREAT,
|
||||
[MoveId.MISTY_EXPLOSION]: RarityTier.COMMON,
|
||||
[MoveId.GRASSY_GLIDE]: RarityTier.COMMON,
|
||||
[MoveId.RISING_VOLTAGE]: RarityTier.COMMON,
|
||||
[MoveId.TERRAIN_PULSE]: RarityTier.COMMON,
|
||||
[MoveId.SKITTER_SMACK]: RarityTier.GREAT,
|
||||
[MoveId.BURNING_JEALOUSY]: RarityTier.GREAT,
|
||||
[MoveId.LASH_OUT]: RarityTier.GREAT,
|
||||
[MoveId.POLTERGEIST]: RarityTier.ULTRA,
|
||||
[MoveId.CORROSIVE_GAS]: RarityTier.COMMON,
|
||||
[MoveId.COACHING]: RarityTier.COMMON,
|
||||
[MoveId.FLIP_TURN]: RarityTier.COMMON,
|
||||
[MoveId.TRIPLE_AXEL]: RarityTier.COMMON,
|
||||
[MoveId.DUAL_WINGBEAT]: RarityTier.COMMON,
|
||||
[MoveId.SCORCHING_SANDS]: RarityTier.GREAT,
|
||||
[MoveId.TERA_BLAST]: RarityTier.GREAT,
|
||||
[MoveId.ICE_SPINNER]: RarityTier.GREAT,
|
||||
[MoveId.SNOWSCAPE]: RarityTier.COMMON,
|
||||
[MoveId.POUNCE]: RarityTier.COMMON,
|
||||
[MoveId.TRAILBLAZE]: RarityTier.COMMON,
|
||||
[MoveId.CHILLING_WATER]: RarityTier.COMMON,
|
||||
[MoveId.HARD_PRESS]: RarityTier.GREAT,
|
||||
[MoveId.DRAGON_CHEER]: RarityTier.COMMON,
|
||||
[MoveId.ALLURING_VOICE]: RarityTier.GREAT,
|
||||
[MoveId.TEMPER_FLARE]: RarityTier.GREAT,
|
||||
[MoveId.SUPERCELL_SLAM]: RarityTier.GREAT,
|
||||
[MoveId.PSYCHIC_NOISE]: RarityTier.GREAT,
|
||||
[MoveId.UPPER_HAND]: RarityTier.COMMON,
|
||||
};
|
||||
|
@ -16,7 +16,7 @@ import type { MoveId } from "#enums/move-id";
|
||||
import type { MoveSourceType } from "#enums/move-source-type";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { TrainerVariant } from "#enums/trainer-variant";
|
||||
@ -457,13 +457,13 @@ export class SingleGenerationChallenge extends Challenge {
|
||||
.setBattleType(BattleType.TRAINER)
|
||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc(trainerTypes, true))
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [
|
||||
RewardTier.ROGUE,
|
||||
RewardTier.ROGUE,
|
||||
RewardTier.ULTRA,
|
||||
RewardTier.ULTRA,
|
||||
RewardTier.ULTRA,
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
],
|
||||
allowLuckUpgrades: false,
|
||||
});
|
||||
@ -474,14 +474,14 @@ export class SingleGenerationChallenge extends Challenge {
|
||||
.setBattleType(BattleType.TRAINER)
|
||||
.setSeedOffsetWave(ClassicFixedBossWaves.EVIL_GRUNT_1)
|
||||
.setGetTrainerFunc(getRandomTrainerFunc(trainerTypes, true))
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [
|
||||
RewardTier.ROGUE,
|
||||
RewardTier.ROGUE,
|
||||
RewardTier.ULTRA,
|
||||
RewardTier.ULTRA,
|
||||
RewardTier.ULTRA,
|
||||
RewardTier.ULTRA,
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
],
|
||||
allowLuckUpgrades: false,
|
||||
});
|
||||
|
@ -3,8 +3,8 @@ import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import type { HeldItem } from "#items/held-item";
|
||||
import type { Rewards } from "#items/reward";
|
||||
import type { TrainerItem } from "#items/trainer-item";
|
||||
import type { ModifierTypes } from "#modifiers/modifier-type";
|
||||
import type { Move } from "#moves/move";
|
||||
|
||||
export const allAbilities: Ability[] = [];
|
||||
@ -15,4 +15,4 @@ export const allHeldItems: Record<HeldItemId, HeldItem> = {};
|
||||
export const allTrainerItems: Record<TrainerItemId, TrainerItem> = {};
|
||||
|
||||
// TODO: Figure out what this is used for and provide an appropriate tsdoc comment
|
||||
export const modifierTypes = {} as ModifierTypes;
|
||||
export const allRewards = {} as Rewards;
|
||||
|
@ -69,7 +69,7 @@ import { MoveUsedEvent } from "#events/battle-scene";
|
||||
import type { EnemyPokemon, Pokemon } from "#field/pokemon";
|
||||
import { applyHeldItems } from "#items/all-held-items";
|
||||
import { BerryHeldItem, berryTypeToHeldItem } from "#items/berry";
|
||||
import { HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { TrainerItemEffect } from "#items/trainer-item";
|
||||
import { applyMoveAttrs } from "#moves/apply-attrs";
|
||||
import { invalidAssistMoves, invalidCopycatMoves, invalidMetronomeMoves, invalidMirrorMoveMoves, invalidSketchMoves, invalidSleepTalkMoves } from "#moves/invalid-moves";
|
||||
@ -856,7 +856,7 @@ export abstract class Move implements Localizable {
|
||||
if (!this.hasAttr("TypelessAttr")) {
|
||||
globalScene.arena.applyTags(WeakenMoveTypeTag, simulated, typeChangeHolder.value, power);
|
||||
applyHeldItems(HeldItemEffect.ATTACK_TYPE_BOOST, {
|
||||
pokemon: source,
|
||||
pokemon: source,
|
||||
moveType: typeChangeHolder.value,
|
||||
movePower: power,
|
||||
});
|
||||
@ -2636,14 +2636,14 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr {
|
||||
}
|
||||
|
||||
const stolenItem = heldItems[user.randBattleSeedInt(heldItems.length)];
|
||||
|
||||
|
||||
if (!globalScene.tryTransferHeldItem(stolenItem, target, user, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:stoleItem",
|
||||
{ pokemonName: getPokemonNameWithAffix(user),
|
||||
targetName: getPokemonNameWithAffix(target),
|
||||
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:stoleItem",
|
||||
{ pokemonName: getPokemonNameWithAffix(user),
|
||||
targetName: getPokemonNameWithAffix(target),
|
||||
itemName: allHeldItems[stolenItem].name
|
||||
}
|
||||
));
|
||||
@ -2719,16 +2719,16 @@ export class RemoveHeldItemAttr extends MoveEffectAttr {
|
||||
globalScene.updateItems(target.isPlayer());
|
||||
|
||||
if (this.berriesOnly) {
|
||||
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:incineratedItem",
|
||||
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:incineratedItem",
|
||||
{ pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: allHeldItems[removedItem].name }));
|
||||
} else {
|
||||
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:knockedOffItem",
|
||||
globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:knockedOffItem",
|
||||
{ pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: allHeldItems[removedItem].name }));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
|
||||
const heldItems = target.getHeldItems();
|
||||
return heldItems.length ? 5 : 0;
|
||||
@ -2775,7 +2775,7 @@ export class EatBerryAttr extends MoveEffectAttr {
|
||||
// check for berry pouch preservation
|
||||
globalScene.applyPlayerItems(TrainerItemEffect.PRESERVE_BERRY, {pokemon: pokemon, doPreserve: preserve});
|
||||
if (!preserve.value) {
|
||||
this.reduceBerryModifier(pokemon);
|
||||
this.reduceBerryItem(pokemon);
|
||||
}
|
||||
|
||||
// Don't update harvest for berries preserved via Berry pouch (no item dupes lol)
|
||||
@ -2788,7 +2788,7 @@ export class EatBerryAttr extends MoveEffectAttr {
|
||||
return target.getHeldItems().filter(m => isItemInCategory(m, HeldItemCategoryId.BERRY));
|
||||
}
|
||||
|
||||
reduceBerryModifier(target: Pokemon) {
|
||||
reduceBerryItem(target: Pokemon) {
|
||||
if (this.chosenBerry) {
|
||||
target.loseHeldItem(this.chosenBerry);
|
||||
}
|
||||
@ -2850,7 +2850,7 @@ export class StealEatBerryAttr extends EatBerryAttr {
|
||||
applyAbAttrs("PostItemLostAbAttr", {pokemon: target});
|
||||
const message = i18next.t("battle:stealEatBerry", { pokemonName: user.name, targetName: target.name, berryName: allHeldItems[this.chosenBerry].name });
|
||||
globalScene.phaseManager.queueMessage(message);
|
||||
this.reduceBerryModifier(target);
|
||||
this.reduceBerryItem(target);
|
||||
this.eatBerry(user, target);
|
||||
|
||||
return true;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import type { IEggOptions } from "#data/egg";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
@ -150,7 +150,7 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
},
|
||||
async () => {
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
// Battle the stat trainer for an Egg and great rewards
|
||||
// Battle the stat trainer for an Egg and great allRewards
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
await transitionMysteryEncounterIntroVisuals();
|
||||
@ -164,8 +164,8 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.epic`));
|
||||
setEncounterRewards(
|
||||
{
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH],
|
||||
guaranteedModifierTiers: [RewardTier.ROGUE, RewardTier.ULTRA],
|
||||
guaranteedRewardFuncs: [allRewards.SACRED_ASH],
|
||||
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ULTRA],
|
||||
fillRemaining: true,
|
||||
},
|
||||
[eggOptions],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { speciesStarterCosts } from "#balance/starters";
|
||||
import { allTrainerItems, modifierTypes } from "#data/data-lists";
|
||||
import { allRewards, allTrainerItems } from "#data/data-lists";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
@ -136,7 +136,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB
|
||||
})
|
||||
.withOptionPhase(async () => {
|
||||
// Give the player a Shiny Charm
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes.SHINY_CHARM);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards.SHINY_CHARM);
|
||||
leaveEncounterWithoutBattle(true);
|
||||
})
|
||||
.build(),
|
||||
@ -184,7 +184,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -1,22 +1,22 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { RewardPoolType } from "#enums/reward-pool-type";
|
||||
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import { berryTypeToHeldItem } from "#items/berry";
|
||||
import type { ModifierTypeOption } from "#modifiers/modifier-type";
|
||||
import { regenerateModifierPoolThresholds } from "#modifiers/modifier-type";
|
||||
import type { RewardOption } from "#items/reward";
|
||||
import { generateRewardPoolWeights, getRewardPoolForType } from "#items/reward-pool-utils";
|
||||
import { generateRewardOption } from "#items/reward-utils";
|
||||
import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
import {
|
||||
generateModifierTypeOption,
|
||||
getRandomEncounterSpecies,
|
||||
initBattleWithEnemyConfig,
|
||||
leaveEncounterWithoutBattle,
|
||||
@ -88,7 +88,7 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
: globalScene.currentBattle.waveIndex > 40
|
||||
? 4
|
||||
: 2;
|
||||
regenerateModifierPoolThresholds(globalScene.getPlayerParty(), ModifierPoolType.PLAYER, 0);
|
||||
generateRewardPoolWeights(getRewardPoolForType(RewardPoolType.PLAYER), globalScene.getPlayerParty(), 0);
|
||||
encounter.misc = { numBerries };
|
||||
|
||||
const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(bossPokemon);
|
||||
@ -159,20 +159,16 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
}
|
||||
};
|
||||
|
||||
const shopOptions: ModifierTypeOption[] = [];
|
||||
const shopOptions: RewardOption[] = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Generate shop berries
|
||||
const mod = generateModifierTypeOption(modifierTypes.BERRY);
|
||||
const mod = generateRewardOption(allRewards.BERRY);
|
||||
if (mod) {
|
||||
shopOptions.push(mod);
|
||||
}
|
||||
}
|
||||
|
||||
setEncounterRewards(
|
||||
{ guaranteedModifierTypeOptions: shopOptions, fillRemaining: false },
|
||||
undefined,
|
||||
doBerryRewards,
|
||||
);
|
||||
setEncounterRewards({ guaranteedRewardOptions: shopOptions, fillRemaining: false }, undefined, doBerryRewards);
|
||||
await initBattleWithEnemyConfig(globalScene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]);
|
||||
},
|
||||
)
|
||||
@ -190,10 +186,10 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
const speedDiff = fastestPokemon.getStat(Stat.SPD) / (enemySpeed * 1.1);
|
||||
const numBerries: number = encounter.misc.numBerries;
|
||||
|
||||
const shopOptions: ModifierTypeOption[] = [];
|
||||
const shopOptions: RewardOption[] = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Generate shop berries
|
||||
const mod = generateModifierTypeOption(modifierTypes.BERRY);
|
||||
const mod = generateRewardOption(allRewards.BERRY);
|
||||
if (mod) {
|
||||
shopOptions.push(mod);
|
||||
}
|
||||
@ -246,7 +242,7 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
};
|
||||
setEncounterRewards(
|
||||
{
|
||||
guaranteedModifierTypeOptions: shopOptions,
|
||||
guaranteedRewardOptions: shopOptions,
|
||||
fillRemaining: false,
|
||||
},
|
||||
undefined,
|
||||
@ -279,7 +275,7 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
setEncounterExp(fastestPokemon.id, encounter.enemyPartyConfigs[0].pokemonConfigs![0].species.baseExp);
|
||||
setEncounterRewards(
|
||||
{
|
||||
guaranteedModifierTypeOptions: shopOptions,
|
||||
guaranteedRewardOptions: shopOptions,
|
||||
fillRemaining: false,
|
||||
},
|
||||
undefined,
|
||||
@ -301,7 +297,7 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { allHeldItems, allMoves, modifierTypes } from "#data/data-lists";
|
||||
import { allHeldItems, allMoves, allRewards } from "#data/data-lists";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
@ -8,18 +8,18 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import { TrainerSlot } from "#enums/trainer-slot";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import type { ModifierTypeOption } from "#modifiers/modifier-type";
|
||||
import type { RewardOption } from "#items/reward";
|
||||
import { generateRewardOption } from "#items/reward-utils";
|
||||
import { PokemonMove } from "#moves/pokemon-move";
|
||||
import { getEncounterText, showEncounterDialogue } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
import {
|
||||
generateModifierTypeOption,
|
||||
initBattleWithEnemyConfig,
|
||||
leaveEncounterWithoutBattle,
|
||||
selectOptionThenPokemon,
|
||||
@ -285,7 +285,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
moveTutorOptions,
|
||||
};
|
||||
|
||||
// Assigns callback that teaches move before continuing to rewards
|
||||
// Assigns callback that teaches move before continuing to allRewards
|
||||
encounter.onRewards = doBugTypeMoveTutor;
|
||||
|
||||
setEncounterRewards({ fillRemaining: true });
|
||||
@ -305,7 +305,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
// Player shows off their bug types
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
|
||||
// Player gets different rewards depending on the number of bug types they have
|
||||
// Player gets different allRewards depending on the number of bug types they have
|
||||
const numBugTypes = globalScene.getPlayerParty().filter(p => p.isOfType(PokemonType.BUG, true)).length;
|
||||
const numBugTypesText = i18next.t(`${namespace}:numBugTypes`, {
|
||||
count: numBugTypes,
|
||||
@ -314,7 +314,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
|
||||
if (numBugTypes < 2) {
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL],
|
||||
guaranteedRewardFuncs: [allRewards.SUPER_LURE, allRewards.GREAT_BALL],
|
||||
fillRemaining: false,
|
||||
});
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
@ -325,7 +325,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
];
|
||||
} else if (numBugTypes < 4) {
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL],
|
||||
guaranteedRewardFuncs: [allRewards.QUICK_CLAW, allRewards.MAX_LURE, allRewards.ULTRA_BALL],
|
||||
fillRemaining: false,
|
||||
});
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
@ -336,7 +336,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
];
|
||||
} else if (numBugTypes < 6) {
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL],
|
||||
guaranteedRewardFuncs: [allRewards.GRIP_CLAW, allRewards.MAX_LURE, allRewards.ROGUE_BALL],
|
||||
fillRemaining: false,
|
||||
});
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
@ -348,38 +348,38 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
} else {
|
||||
// If the player has any evolution/form change items that are valid for their party,
|
||||
// spawn one of those items in addition to Dynamax Band, Mega Band, and Master Ball
|
||||
const modifierOptions: ModifierTypeOption[] = [generateModifierTypeOption(modifierTypes.MASTER_BALL)!];
|
||||
const specialOptions: ModifierTypeOption[] = [];
|
||||
const rewardOptions: RewardOption[] = [generateRewardOption(allRewards.MASTER_BALL)!];
|
||||
const specialOptions: RewardOption[] = [];
|
||||
|
||||
if (!globalScene.trainerItems.hasItem(TrainerItemId.MEGA_BRACELET)) {
|
||||
modifierOptions.push(generateModifierTypeOption(modifierTypes.MEGA_BRACELET)!);
|
||||
rewardOptions.push(generateRewardOption(allRewards.MEGA_BRACELET)!);
|
||||
}
|
||||
if (!globalScene.trainerItems.hasItem(TrainerItemId.DYNAMAX_BAND)) {
|
||||
modifierOptions.push(generateModifierTypeOption(modifierTypes.DYNAMAX_BAND)!);
|
||||
rewardOptions.push(generateRewardOption(allRewards.DYNAMAX_BAND)!);
|
||||
}
|
||||
const nonRareEvolutionModifier = generateModifierTypeOption(modifierTypes.EVOLUTION_ITEM);
|
||||
if (nonRareEvolutionModifier) {
|
||||
specialOptions.push(nonRareEvolutionModifier);
|
||||
const nonRareEvolutionReward = generateRewardOption(allRewards.EVOLUTION_ITEM);
|
||||
if (nonRareEvolutionReward) {
|
||||
specialOptions.push(nonRareEvolutionReward);
|
||||
}
|
||||
const rareEvolutionModifier = generateModifierTypeOption(modifierTypes.RARE_EVOLUTION_ITEM);
|
||||
if (rareEvolutionModifier) {
|
||||
specialOptions.push(rareEvolutionModifier);
|
||||
const rareEvolutionReward = generateRewardOption(allRewards.RARE_EVOLUTION_ITEM);
|
||||
if (rareEvolutionReward) {
|
||||
specialOptions.push(rareEvolutionReward);
|
||||
}
|
||||
const formChangeModifier = generateModifierTypeOption(modifierTypes.FORM_CHANGE_ITEM);
|
||||
if (formChangeModifier) {
|
||||
specialOptions.push(formChangeModifier);
|
||||
const formChangeReward = generateRewardOption(allRewards.FORM_CHANGE_ITEM);
|
||||
if (formChangeReward) {
|
||||
specialOptions.push(formChangeReward);
|
||||
}
|
||||
const rareFormChangeModifier = generateModifierTypeOption(modifierTypes.RARE_FORM_CHANGE_ITEM);
|
||||
if (rareFormChangeModifier) {
|
||||
specialOptions.push(rareFormChangeModifier);
|
||||
const rareFormChangeReward = generateRewardOption(allRewards.RARE_FORM_CHANGE_ITEM);
|
||||
if (rareFormChangeReward) {
|
||||
specialOptions.push(rareFormChangeReward);
|
||||
}
|
||||
if (specialOptions.length > 0) {
|
||||
// TODO: should this use `randSeedItem`?
|
||||
modifierOptions.push(specialOptions[randSeedInt(specialOptions.length)]);
|
||||
rewardOptions.push(specialOptions[randSeedInt(specialOptions.length)]);
|
||||
}
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: modifierOptions,
|
||||
guaranteedRewardOptions: rewardOptions,
|
||||
fillRemaining: false,
|
||||
});
|
||||
encounter.selectedOption!.dialogue!.selected = [
|
||||
@ -465,12 +465,12 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
chosenPokemon.loseHeldItem(lostItem, false);
|
||||
globalScene.updateItems(true);
|
||||
|
||||
const bugNet = generateModifierTypeOption(modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!;
|
||||
bugNet.type.tier = RewardTier.ROGUE;
|
||||
const bugNet = generateRewardOption(allRewards.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!;
|
||||
bugNet.type.tier = RarityTier.ROGUE;
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: [bugNet],
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED],
|
||||
guaranteedRewardOptions: [bugNet],
|
||||
guaranteedRewardFuncs: [allRewards.REVIVER_SEED],
|
||||
fillRemaining: false,
|
||||
});
|
||||
leaveEncounterWithoutBattle(true);
|
||||
@ -744,7 +744,7 @@ function doBugTypeMoveTutor(): Promise<void> {
|
||||
);
|
||||
}
|
||||
|
||||
// Complete battle and go to rewards
|
||||
// Complete battle and go to allRewards
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
@ -16,13 +16,13 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import type { PlayerPokemon } from "#field/pokemon";
|
||||
import { getHeldItemTier } from "#items/held-item-default-tiers";
|
||||
import { assignItemsFromConfiguration } from "#items/held-item-pool";
|
||||
import { getHeldItemTier } from "#items/held-item-tiers";
|
||||
import { PokemonMove } from "#moves/pokemon-move";
|
||||
import { showEncounterDialogue, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
@ -329,11 +329,11 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||
let numRogue = 0;
|
||||
|
||||
for (const m of items) {
|
||||
const tier = getHeldItemTier(m) ?? RewardTier.ULTRA;
|
||||
const tier = getHeldItemTier(m) ?? RarityTier.ULTRA;
|
||||
const stack = mostHeldItemsPokemon.heldItemManager.getStack(m);
|
||||
if (tier === RewardTier.ROGUE) {
|
||||
if (tier === RarityTier.ROGUE) {
|
||||
numRogue += stack;
|
||||
} else if (tier === RewardTier.ULTRA) {
|
||||
} else if (tier === RarityTier.ULTRA) {
|
||||
numUltra += stack;
|
||||
}
|
||||
mostHeldItemsPokemon.heldItemManager.remove(m, stack);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { EncounterBattleAnim } from "#data/battle-anims";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { BattlerIndex } from "#enums/battler-index";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
@ -219,7 +219,7 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||
|
||||
await hideOricorioPokemon();
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.BATON],
|
||||
guaranteedRewardFuncs: [allRewards.BATON],
|
||||
fillRemaining: true,
|
||||
});
|
||||
await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
@ -160,7 +160,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE
|
||||
.withOptionPhase(async () => {
|
||||
// Give the player 5 Rogue Balls
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes.ROGUE_BALL);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards.ROGUE_BALL);
|
||||
|
||||
// Start encounter with random legendary (7-10 starter strength) that has level additive
|
||||
// If this is a mono-type challenge, always ensure the required type is filtered for
|
||||
@ -204,7 +204,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { timedEventManager } from "#app/global-event-manager";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { allHeldItems, modifierTypes } from "#data/data-lists";
|
||||
import { allHeldItems, allRewards } from "#data/data-lists";
|
||||
import { HeldItemCategoryId, HeldItemId, isItemInCategory } from "#enums/held-item-id";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
@ -34,7 +34,7 @@ const namespace = "mysteryEncounters/delibirdy";
|
||||
/** Berries only */
|
||||
const OPTION_2_ALLOWED_HELD_ITEMS = [HeldItemCategoryId.BERRY, HeldItemId.REVIVER_SEED];
|
||||
|
||||
/** Disallowed items are berries, Reviver Seeds, and Vitamins (form change items and fusion items are not PokemonHeldItemModifiers) */
|
||||
/** Disallowed items are berries, Reviver Seeds, and Vitamins */
|
||||
const OPTION_3_DISALLOWED_HELD_ITEMS = [HeldItemCategoryId.BERRY, HeldItemId.REVIVER_SEED];
|
||||
|
||||
const DELIBIRDY_MONEY_PRICE_MULTIPLIER = 2;
|
||||
@ -61,10 +61,10 @@ const doEventReward = () => {
|
||||
return !fullStack;
|
||||
});
|
||||
if (candidates.length > 0) {
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes[randSeedItem(candidates)]);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards[randSeedItem(candidates)]);
|
||||
} else {
|
||||
// At max stacks, give a Voucher instead
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes.VOUCHER);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards.VOUCHER);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -168,7 +168,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
backupOption();
|
||||
} else {
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes.AMULET_COIN);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards.AMULET_COIN);
|
||||
doEventReward();
|
||||
}
|
||||
|
||||
@ -238,7 +238,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
backupOption();
|
||||
} else {
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes.CANDY_JAR);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards.CANDY_JAR);
|
||||
doEventReward();
|
||||
}
|
||||
} else {
|
||||
@ -249,7 +249,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
backupOption();
|
||||
} else {
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes.BERRY_POUCH);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards.BERRY_POUCH);
|
||||
doEventReward();
|
||||
}
|
||||
}
|
||||
@ -321,7 +321,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
// At max stacks, give the first party pokemon a Shell Bell instead
|
||||
backupOption();
|
||||
} else {
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", modifierTypes.HEALING_CHARM);
|
||||
globalScene.phaseManager.unshiftNew("RewardPhase", allRewards.HEALING_CHARM);
|
||||
doEventReward();
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { leaveEncounterWithoutBattle, setEncounterRewards } from "#mystery-encounters/encounter-phase-utils";
|
||||
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
||||
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
|
||||
import type { ModifierTypeFunc } from "#types/modifier-types";
|
||||
import type { RewardFunc } from "#types/rewards";
|
||||
import { randSeedInt } from "#utils/common";
|
||||
|
||||
/** i18n namespace for encounter */
|
||||
@ -59,23 +59,23 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = MysteryEncounterBu
|
||||
},
|
||||
async () => {
|
||||
// Choose TMs
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
const rewards: RewardFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 5) {
|
||||
// 2/2/1 weight on TM rarity
|
||||
const roll = randSeedInt(5);
|
||||
if (roll < 2) {
|
||||
modifiers.push(modifierTypes.TM_COMMON);
|
||||
rewards.push(allRewards.TM_COMMON);
|
||||
} else if (roll < 4) {
|
||||
modifiers.push(modifierTypes.TM_GREAT);
|
||||
rewards.push(allRewards.TM_GREAT);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.TM_ULTRA);
|
||||
rewards.push(allRewards.TM_ULTRA);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: modifiers,
|
||||
guaranteedRewardFuncs: rewards,
|
||||
fillRemaining: false,
|
||||
});
|
||||
leaveEncounterWithoutBattle();
|
||||
@ -88,21 +88,21 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = MysteryEncounterBu
|
||||
},
|
||||
async () => {
|
||||
// Choose Vitamins
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
const rewards: RewardFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 3) {
|
||||
// 2/1 weight on base stat booster vs PP Up
|
||||
const roll = randSeedInt(3);
|
||||
if (roll === 0) {
|
||||
modifiers.push(modifierTypes.PP_UP);
|
||||
rewards.push(allRewards.PP_UP);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.BASE_STAT_BOOSTER);
|
||||
rewards.push(allRewards.BASE_STAT_BOOSTER);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: modifiers,
|
||||
guaranteedRewardFuncs: rewards,
|
||||
fillRemaining: false,
|
||||
});
|
||||
leaveEncounterWithoutBattle();
|
||||
@ -115,21 +115,21 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = MysteryEncounterBu
|
||||
},
|
||||
async () => {
|
||||
// Choose X Items
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
const rewards: RewardFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 5) {
|
||||
// 4/1 weight on base stat booster vs Dire Hit
|
||||
const roll = randSeedInt(5);
|
||||
if (roll === 0) {
|
||||
modifiers.push(modifierTypes.DIRE_HIT);
|
||||
rewards.push(allRewards.DIRE_HIT);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.TEMP_STAT_STAGE_BOOSTER);
|
||||
rewards.push(allRewards.TEMP_STAT_STAGE_BOOSTER);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: modifiers,
|
||||
guaranteedRewardFuncs: rewards,
|
||||
fillRemaining: false,
|
||||
});
|
||||
leaveEncounterWithoutBattle();
|
||||
@ -142,25 +142,25 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = MysteryEncounterBu
|
||||
},
|
||||
async () => {
|
||||
// Choose Pokeballs
|
||||
const modifiers: ModifierTypeFunc[] = [];
|
||||
const rewards: RewardFunc[] = [];
|
||||
let i = 0;
|
||||
while (i < 4) {
|
||||
// 10/30/20/5 weight on pokeballs
|
||||
const roll = randSeedInt(65);
|
||||
if (roll < 10) {
|
||||
modifiers.push(modifierTypes.POKEBALL);
|
||||
rewards.push(allRewards.POKEBALL);
|
||||
} else if (roll < 40) {
|
||||
modifiers.push(modifierTypes.GREAT_BALL);
|
||||
rewards.push(allRewards.GREAT_BALL);
|
||||
} else if (roll < 60) {
|
||||
modifiers.push(modifierTypes.ULTRA_BALL);
|
||||
rewards.push(allRewards.ULTRA_BALL);
|
||||
} else {
|
||||
modifiers.push(modifierTypes.ROGUE_BALL);
|
||||
rewards.push(allRewards.ROGUE_BALL);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: modifiers,
|
||||
guaranteedRewardFuncs: rewards,
|
||||
fillRemaining: false,
|
||||
});
|
||||
leaveEncounterWithoutBattle();
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Stat } from "#enums/stat";
|
||||
import type { PlayerPokemon } from "#field/pokemon";
|
||||
import { generateRewardOption } from "#items/reward-utils";
|
||||
import type { PokemonMove } from "#moves/pokemon-move";
|
||||
import {
|
||||
generateModifierTypeOption,
|
||||
leaveEncounterWithoutBattle,
|
||||
selectPokemonForOption,
|
||||
setEncounterExp,
|
||||
@ -96,15 +96,15 @@ export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ATK])!,
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.DEF])!,
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(modifierTypes.RARER_CANDY)!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.ATK])!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.DEF])!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateRewardOption(allRewards.DIRE_HIT)!,
|
||||
generateRewardOption(allRewards.RARER_CANDY)!,
|
||||
];
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: modifiers,
|
||||
guaranteedRewardOptions: modifiers,
|
||||
fillRemaining: false,
|
||||
});
|
||||
}
|
||||
@ -144,15 +144,15 @@ export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPATK])!,
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPDEF])!,
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(modifierTypes.DIRE_HIT)!,
|
||||
generateModifierTypeOption(modifierTypes.RARER_CANDY)!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.SPATK])!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.SPDEF])!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateRewardOption(allRewards.DIRE_HIT)!,
|
||||
generateRewardOption(allRewards.RARER_CANDY)!,
|
||||
];
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: modifiers,
|
||||
guaranteedRewardOptions: modifiers,
|
||||
fillRemaining: false,
|
||||
});
|
||||
}
|
||||
@ -192,15 +192,15 @@ export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder.with
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
if (encounter.misc.correctMove) {
|
||||
const modifiers = [
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ACC])!,
|
||||
generateModifierTypeOption(modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateModifierTypeOption(modifierTypes.GREAT_BALL)!,
|
||||
generateModifierTypeOption(modifierTypes.IV_SCANNER)!,
|
||||
generateModifierTypeOption(modifierTypes.RARER_CANDY)!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.ACC])!,
|
||||
generateRewardOption(allRewards.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!,
|
||||
generateRewardOption(allRewards.GREAT_BALL)!,
|
||||
generateRewardOption(allRewards.IV_SCANNER)!,
|
||||
generateRewardOption(allRewards.RARER_CANDY)!,
|
||||
];
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: modifiers,
|
||||
guaranteedRewardOptions: modifiers,
|
||||
fillRemaining: false,
|
||||
});
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w
|
||||
}
|
||||
}
|
||||
|
||||
// No rewards
|
||||
// No allRewards
|
||||
leaveEncounterWithoutBattle(true);
|
||||
},
|
||||
)
|
||||
|
@ -1,14 +1,16 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RewardPoolType } from "#enums/reward-pool-type";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { ModifierTypeOption } from "#modifiers/modifier-type";
|
||||
import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#modifiers/modifier-type";
|
||||
import type { RewardOption, TrainerItemReward } from "#items/reward";
|
||||
import { generatePlayerRewardOptions, generateRewardPoolWeights, getRewardPoolForType } from "#items/reward-pool-utils";
|
||||
import { isTmReward } from "#items/reward-utils";
|
||||
import { queueEncounterMessage } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
import {
|
||||
@ -89,18 +91,18 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
// Waves 10-40 GREAT, 60-120 ULTRA, 120-160 ROGUE, 160-180 MASTER
|
||||
const tier =
|
||||
globalScene.currentBattle.waveIndex > 160
|
||||
? RewardTier.MASTER
|
||||
? RarityTier.MASTER
|
||||
: globalScene.currentBattle.waveIndex > 120
|
||||
? RewardTier.ROGUE
|
||||
? RarityTier.ROGUE
|
||||
: globalScene.currentBattle.waveIndex > 40
|
||||
? RewardTier.ULTRA
|
||||
: RewardTier.GREAT;
|
||||
regenerateModifierPoolThresholds(globalScene.getPlayerParty(), ModifierPoolType.PLAYER, 0);
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs and Candy Jar excluded from possible rewards as they're too swingy in value for a singular item reward
|
||||
while (!item || item.type.id.includes("TM_") || item.type.id === "CANDY_JAR") {
|
||||
item = getPlayerModifierTypeOptions(1, globalScene.getPlayerParty(), [], {
|
||||
guaranteedModifierTiers: [tier],
|
||||
? RarityTier.ULTRA
|
||||
: RarityTier.GREAT;
|
||||
generateRewardPoolWeights(getRewardPoolForType(RewardPoolType.PLAYER), globalScene.getPlayerParty(), 0);
|
||||
let item: RewardOption | null = null;
|
||||
// TMs and Candy Jar excluded from possible allRewards as they're too swingy in value for a singular item reward
|
||||
while (!item || isTmReward(item.type) || (item.type as TrainerItemReward).itemId === TrainerItemId.CANDY_JAR) {
|
||||
item = generatePlayerRewardOptions(1, globalScene.getPlayerParty(), [], {
|
||||
guaranteedRarityTiers: [tier],
|
||||
allowLuckUpgrades: false,
|
||||
})[0];
|
||||
}
|
||||
@ -151,9 +153,9 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
async () => {
|
||||
// Pick battle
|
||||
// Pokemon will randomly boost 1 stat by 2 stages
|
||||
const item = globalScene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
const item = globalScene.currentBattle.mysteryEncounter!.misc as RewardOption;
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: [item],
|
||||
guaranteedRewardOptions: [item],
|
||||
fillRemaining: false,
|
||||
});
|
||||
await initBattleWithEnemyConfig(globalScene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]);
|
||||
@ -175,9 +177,9 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
.withOptionPhase(async () => {
|
||||
// Pick steal
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
const item = globalScene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption;
|
||||
const item = globalScene.currentBattle.mysteryEncounter!.misc as RewardOption;
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: [item],
|
||||
guaranteedRewardOptions: [item],
|
||||
fillRemaining: false,
|
||||
});
|
||||
|
||||
@ -199,7 +201,7 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder.
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { SpeciesFormChangeActiveTrigger } from "#data/form-change-triggers";
|
||||
import { getPokeballAtlasKey, getPokeballTintColor } from "#data/pokeball";
|
||||
import { FieldPosition } from "#enums/field-position";
|
||||
@ -160,7 +160,7 @@ export const FunAndGamesEncounter: MysteryEncounter = MysteryEncounterBuilder.wi
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
await transitionMysteryEncounterIntroVisuals(true, true);
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
@ -281,21 +281,21 @@ function handleNextTurn() {
|
||||
if (healthRatio < 0.03) {
|
||||
// Grand prize
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.MULTI_LENS],
|
||||
guaranteedRewardFuncs: [allRewards.MULTI_LENS],
|
||||
fillRemaining: false,
|
||||
});
|
||||
resultMessageKey = `${namespace}:best_result`;
|
||||
} else if (healthRatio < 0.15) {
|
||||
// 2nd prize
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.SCOPE_LENS],
|
||||
guaranteedRewardFuncs: [allRewards.SCOPE_LENS],
|
||||
fillRemaining: false,
|
||||
});
|
||||
resultMessageKey = `${namespace}:great_result`;
|
||||
} else if (healthRatio < 0.33) {
|
||||
// 3rd prize
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.WIDE_LENS],
|
||||
guaranteedRewardFuncs: [allRewards.WIDE_LENS],
|
||||
fillRemaining: false,
|
||||
});
|
||||
resultMessageKey = `${namespace}:good_result`;
|
||||
|
@ -8,22 +8,23 @@ import { getPokeballAtlasKey, getPokeballTintColor } from "#data/pokeball";
|
||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { getTypeRgb } from "#data/type";
|
||||
import { HeldItemCategoryId, type HeldItemId, isItemInCategory } from "#enums/held-item-id";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import type { PokeballType } from "#enums/pokeball";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RewardPoolType } from "#enums/reward-pool-type";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerSlot } from "#enums/trainer-slot";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { doShinySparkleAnim } from "#field/anims";
|
||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import { EnemyPokemon } from "#field/pokemon";
|
||||
import { getHeldItemTier } from "#items/held-item-tiers";
|
||||
import { getHeldItemTier } from "#items/held-item-default-tiers";
|
||||
import type { RewardOption } from "#items/reward";
|
||||
import { generatePlayerRewardOptions, generateRewardPoolWeights, getRewardPoolForType } from "#items/reward-pool-utils";
|
||||
import { isTmReward } from "#items/reward-utils";
|
||||
import { TrainerItemEffect } from "#items/trainer-item";
|
||||
import type { ModifierTypeOption } from "#modifiers/modifier-type";
|
||||
import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#modifiers/modifier-type";
|
||||
import { PokemonMove } from "#moves/pokemon-move";
|
||||
import { getEncounterText, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import {
|
||||
@ -413,26 +414,26 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil
|
||||
const chosenPokemon: PlayerPokemon = encounter.misc.chosenPokemon;
|
||||
|
||||
// Check tier of the traded item, the received item will be one tier up
|
||||
let tier = getHeldItemTier(heldItemId) ?? RewardTier.GREAT;
|
||||
let tier = getHeldItemTier(heldItemId) ?? RarityTier.GREAT;
|
||||
|
||||
// Increment tier by 1
|
||||
if (tier < RewardTier.MASTER) {
|
||||
if (tier < RarityTier.MASTER) {
|
||||
tier++;
|
||||
}
|
||||
|
||||
regenerateModifierPoolThresholds(party, ModifierPoolType.PLAYER, 0);
|
||||
let item: ModifierTypeOption | null = null;
|
||||
// TMs excluded from possible rewards
|
||||
while (!item || item.type.id.includes("TM_")) {
|
||||
item = getPlayerModifierTypeOptions(1, party, [], {
|
||||
guaranteedModifierTiers: [tier],
|
||||
generateRewardPoolWeights(getRewardPoolForType(RewardPoolType.PLAYER), party, 0);
|
||||
let item: RewardOption | null = null;
|
||||
// TMs excluded from possible allRewards
|
||||
while (!item || isTmReward(item.type)) {
|
||||
item = generatePlayerRewardOptions(1, party, [], {
|
||||
guaranteedRarityTiers: [tier],
|
||||
allowLuckUpgrades: false,
|
||||
})[0];
|
||||
}
|
||||
|
||||
encounter.setDialogueToken("itemName", item.type.name);
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: [item],
|
||||
guaranteedRewardOptions: [item],
|
||||
fillRemaining: false,
|
||||
});
|
||||
|
||||
@ -458,7 +459,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
import { initBattleWithEnemyConfig, setEncounterRewards } from "#mystery-encounters/encounter-phase-utils";
|
||||
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
||||
@ -147,7 +147,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter = MysteryEncounter
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0];
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM],
|
||||
guaranteedRewardFuncs: [allRewards.TM_COMMON, allRewards.TM_GREAT, allRewards.MEMORY_MUSHROOM],
|
||||
fillRemaining: true,
|
||||
});
|
||||
|
||||
@ -175,7 +175,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter = MysteryEncounter
|
||||
const config: EnemyPartyConfig = encounter.enemyPartyConfigs[1];
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTiers: [RewardTier.ULTRA, RewardTier.ULTRA, RewardTier.GREAT, RewardTier.GREAT],
|
||||
guaranteedRarityTiers: [RarityTier.ULTRA, RarityTier.ULTRA, RarityTier.GREAT, RarityTier.GREAT],
|
||||
fillRemaining: true,
|
||||
});
|
||||
|
||||
@ -206,7 +206,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter = MysteryEncounter
|
||||
encounter.expMultiplier = 0.9;
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTiers: [RewardTier.ROGUE, RewardTier.ROGUE, RewardTier.ULTRA, RewardTier.GREAT],
|
||||
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ROGUE, RarityTier.ULTRA, RarityTier.GREAT],
|
||||
fillRemaining: true,
|
||||
});
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { MoveId } from "#enums/move-id";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
@ -141,25 +141,25 @@ export const MysteriousChestEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT) {
|
||||
// Choose between 2 COMMON / 2 GREAT tier items (20%)
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTiers: [RewardTier.COMMON, RewardTier.COMMON, RewardTier.GREAT, RewardTier.GREAT],
|
||||
guaranteedRarityTiers: [RarityTier.COMMON, RarityTier.COMMON, RarityTier.GREAT, RarityTier.GREAT],
|
||||
});
|
||||
// Display result message then proceed to rewards
|
||||
// Display result message then proceed to allRewards
|
||||
queueEncounterMessage(`${namespace}:option.1.normal`);
|
||||
leaveEncounterWithoutBattle();
|
||||
} else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT) {
|
||||
// Choose between 3 ULTRA tier items (30%)
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTiers: [RewardTier.ULTRA, RewardTier.ULTRA, RewardTier.ULTRA],
|
||||
guaranteedRarityTiers: [RarityTier.ULTRA, RarityTier.ULTRA, RarityTier.ULTRA],
|
||||
});
|
||||
// Display result message then proceed to rewards
|
||||
// Display result message then proceed to allRewards
|
||||
queueEncounterMessage(`${namespace}:option.1.good`);
|
||||
leaveEncounterWithoutBattle();
|
||||
} else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT - ROGUE_REWARDS_PERCENT) {
|
||||
// Choose between 2 ROGUE tier items (10%)
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTiers: [RewardTier.ROGUE, RewardTier.ROGUE],
|
||||
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ROGUE],
|
||||
});
|
||||
// Display result message then proceed to rewards
|
||||
// Display result message then proceed to allRewards
|
||||
queueEncounterMessage(`${namespace}:option.1.great`);
|
||||
leaveEncounterWithoutBattle();
|
||||
} else if (
|
||||
@ -168,9 +168,9 @@ export const MysteriousChestEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
) {
|
||||
// Choose 1 MASTER tier item (5%)
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTiers: [RewardTier.MASTER],
|
||||
guaranteedRarityTiers: [RarityTier.MASTER],
|
||||
});
|
||||
// Display result message then proceed to rewards
|
||||
// Display result message then proceed to allRewards
|
||||
queueEncounterMessage(`${namespace}:option.1.amazing`);
|
||||
leaveEncounterWithoutBattle();
|
||||
} else {
|
||||
@ -208,7 +208,7 @@ export const MysteriousChestEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -125,7 +125,7 @@ export const SafariZoneEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -227,7 +227,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { CustomPokemonData } from "#data/pokemon-data";
|
||||
import { AiType } from "#enums/ai-type";
|
||||
import { BattlerIndex } from "#enums/battler-index";
|
||||
@ -116,7 +116,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
||||
// Pick battle
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS],
|
||||
guaranteedRewardFuncs: [allRewards.LEFTOVERS],
|
||||
fillRemaining: true,
|
||||
});
|
||||
encounter.startOfBattleEffects.push({
|
||||
@ -163,7 +163,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil
|
||||
// Steal the Snorlax's Leftovers
|
||||
const instance = globalScene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS],
|
||||
guaranteedRewardFuncs: [allRewards.LEFTOVERS],
|
||||
fillRemaining: false,
|
||||
});
|
||||
// Snorlax exp to Pokemon that did the stealing
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
@ -13,11 +13,10 @@ import { TrainerSlot } from "#enums/trainer-slot";
|
||||
import { getBiomeKey } from "#field/arena";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { EnemyPokemon } from "#field/pokemon";
|
||||
import { getPartyLuckValue } from "#modifiers/modifier-type";
|
||||
import { generateRewardOption } from "#items/reward-utils";
|
||||
import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
import {
|
||||
generateModifierTypeOption,
|
||||
initBattleWithEnemyConfig,
|
||||
setEncounterExp,
|
||||
setEncounterRewards,
|
||||
@ -34,6 +33,7 @@ import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encou
|
||||
import { MoneyRequirement, WaveModulusRequirement } from "#mystery-encounters/mystery-encounter-requirements";
|
||||
import { PokemonData } from "#system/pokemon-data";
|
||||
import { randSeedInt } from "#utils/common";
|
||||
import { getPartyLuckValue } from "#utils/party";
|
||||
|
||||
/** the i18n namespace for this encounter */
|
||||
const namespace = "mysteryEncounters/teleportingHijinks";
|
||||
@ -173,10 +173,10 @@ export const TeleportingHijinksEncounter: MysteryEncounter = MysteryEncounterBui
|
||||
],
|
||||
};
|
||||
|
||||
const magnet = generateModifierTypeOption(modifierTypes.ATTACK_TYPE_BOOSTER, [PokemonType.STEEL])!;
|
||||
const metalCoat = generateModifierTypeOption(modifierTypes.ATTACK_TYPE_BOOSTER, [PokemonType.ELECTRIC])!;
|
||||
const magnet = generateRewardOption(allRewards.ATTACK_TYPE_BOOSTER, [PokemonType.STEEL])!;
|
||||
const metalCoat = generateRewardOption(allRewards.ATTACK_TYPE_BOOSTER, [PokemonType.ELECTRIC])!;
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: [magnet, metalCoat],
|
||||
guaranteedRewardOptions: [magnet, metalCoat],
|
||||
fillRemaining: true,
|
||||
});
|
||||
await transitionMysteryEncounterIntroVisuals(true, true);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { speciesStarterCosts } from "#balance/starters";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import type { IEggOptions } from "#data/egg";
|
||||
import { getPokeballTintColor } from "#data/pokeball";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
@ -294,7 +294,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount
|
||||
const eggOptions = getEggOptions(pokemon1CommonEggs, pokemon1RareEggs);
|
||||
setEncounterRewards(
|
||||
{
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.SOOTHE_BELL],
|
||||
guaranteedRewardFuncs: [allRewards.SOOTHE_BELL],
|
||||
fillRemaining: true,
|
||||
},
|
||||
eggOptions,
|
||||
@ -304,7 +304,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount
|
||||
// Remove all Pokemon from the party except the chosen Pokemon
|
||||
removePokemonFromPartyAndStoreHeldItems(encounter, pokemon1);
|
||||
|
||||
// Configure outro dialogue for egg rewards
|
||||
// Configure outro dialogue for egg allRewards
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
@ -353,7 +353,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount
|
||||
const eggOptions = getEggOptions(pokemon2CommonEggs, pokemon2RareEggs);
|
||||
setEncounterRewards(
|
||||
{
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.SOOTHE_BELL],
|
||||
guaranteedRewardFuncs: [allRewards.SOOTHE_BELL],
|
||||
fillRemaining: true,
|
||||
},
|
||||
eggOptions,
|
||||
@ -363,7 +363,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount
|
||||
// Remove all Pokemon from the party except the chosen Pokemon
|
||||
removePokemonFromPartyAndStoreHeldItems(encounter, pokemon2);
|
||||
|
||||
// Configure outro dialogue for egg rewards
|
||||
// Configure outro dialogue for egg allRewards
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
@ -412,7 +412,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount
|
||||
const eggOptions = getEggOptions(pokemon3CommonEggs, pokemon3RareEggs);
|
||||
setEncounterRewards(
|
||||
{
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.SOOTHE_BELL],
|
||||
guaranteedRewardFuncs: [allRewards.SOOTHE_BELL],
|
||||
fillRemaining: true,
|
||||
},
|
||||
eggOptions,
|
||||
@ -422,7 +422,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount
|
||||
// Remove all Pokemon from the party except the chosen Pokemon
|
||||
removePokemonFromPartyAndStoreHeldItems(encounter, pokemon3);
|
||||
|
||||
// Configure outro dialogue for egg rewards
|
||||
// Configure outro dialogue for egg allRewards
|
||||
encounter.dialogue.outro = [
|
||||
{
|
||||
speaker: trainerNameKey,
|
||||
@ -640,7 +640,7 @@ function onGameOver() {
|
||||
const chosenPokemon = encounter.misc.chosenPokemon;
|
||||
chosenPokemon.friendship = 0;
|
||||
|
||||
// Clear all rewards that would have been earned
|
||||
// Clear all allRewards that would have been earned
|
||||
encounter.doEncounterRewards = undefined;
|
||||
|
||||
// Set flag that encounter was failed
|
||||
|
@ -238,7 +238,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { CustomPokemonData } from "#data/pokemon-data";
|
||||
import { BattlerIndex } from "#enums/battler-index";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
@ -193,7 +193,7 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder
|
||||
// Pick battle
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.SOUL_DEW],
|
||||
guaranteedRewardFuncs: [allRewards.SOUL_DEW],
|
||||
fillRemaining: true,
|
||||
});
|
||||
encounter.startOfBattleEffects.push(
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { applyAbAttrs } from "#abilities/apply-ab-attrs";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { SpeciesFormChangeAbilityTrigger } from "#data/form-change-triggers";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
@ -11,13 +11,13 @@ import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { generateRewardOption } from "#items/reward-utils";
|
||||
import { showEncounterDialogue, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils";
|
||||
import {
|
||||
generateModifierTypeOption,
|
||||
initBattleWithEnemyConfig,
|
||||
leaveEncounterWithoutBattle,
|
||||
setEncounterRewards,
|
||||
@ -117,7 +117,7 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = MysteryEncounter
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Spawn 5 trainer battles back to back with Macho Brace in rewards
|
||||
// Spawn 5 trainer battles back to back with Macho Brace in allRewards
|
||||
globalScene.currentBattle.mysteryEncounter!.doContinueEncounter = async () => {
|
||||
await endTrainerBattleAndShowDialogue();
|
||||
};
|
||||
@ -140,7 +140,7 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = MysteryEncounter
|
||||
// Refuse the challenge, they full heal the party and give the player a Rarer Candy
|
||||
globalScene.phaseManager.unshiftNew("PartyHealPhase", true);
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [modifierTypes.RARER_CANDY],
|
||||
guaranteedRewardFuncs: [allRewards.RARER_CANDY],
|
||||
fillRemaining: false,
|
||||
});
|
||||
leaveEncounterWithoutBattle();
|
||||
@ -156,17 +156,17 @@ async function spawnNextTrainerOrEndEncounter() {
|
||||
await showEncounterDialogue(`${namespace}:victory`, `${namespace}:speaker`);
|
||||
|
||||
// Give 10x Voucher
|
||||
const newModifier = modifierTypes.VOUCHER_PREMIUM().newModifier();
|
||||
globalScene.addModifier(newModifier);
|
||||
const reward = allRewards.VOUCHER_PREMIUM();
|
||||
globalScene.applyReward(reward, {});
|
||||
globalScene.playSound("item_fanfare");
|
||||
await showEncounterText(i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name }));
|
||||
await showEncounterText(i18next.t("battle:rewardGain", { modifierName: reward.name }));
|
||||
|
||||
await showEncounterDialogue(`${namespace}:victory_2`, `${namespace}:speaker`);
|
||||
globalScene.ui.clearText(); // Clears "Winstrate" title from screen as rewards get animated in
|
||||
const machoBrace = generateModifierTypeOption(modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE)!;
|
||||
machoBrace.type.tier = RewardTier.MASTER;
|
||||
globalScene.ui.clearText(); // Clears "Winstrate" title from screen as allRewards get animated in
|
||||
const machoBrace = generateRewardOption(allRewards.MYSTERY_ENCOUNTER_MACHO_BRACE)!;
|
||||
machoBrace.type.tier = RarityTier.MASTER;
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeOptions: [machoBrace],
|
||||
guaranteedRewardOptions: [machoBrace],
|
||||
fillRemaining: false,
|
||||
});
|
||||
encounter.doContinueEncounter = undefined;
|
||||
|
@ -346,7 +346,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Leave encounter with no rewards or exp
|
||||
// Leave encounter with no allRewards or exp
|
||||
leaveEncounterWithoutBattle(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -8,7 +8,7 @@ import { MoveUseMode } from "#enums/move-use-mode";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import { assignItemToFirstFreePokemon } from "#items/item-utility";
|
||||
@ -167,7 +167,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde
|
||||
const encounter = globalScene.currentBattle.mysteryEncounter!;
|
||||
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTiers: [RewardTier.ROGUE, RewardTier.ROGUE, RewardTier.ULTRA, RewardTier.GREAT],
|
||||
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ROGUE, RarityTier.ULTRA, RarityTier.GREAT],
|
||||
fillRemaining: true,
|
||||
});
|
||||
encounter.startOfBattleEffects.push(
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { allSpecies, modifierTypes } from "#data/data-lists";
|
||||
import { allRewards, allSpecies } from "#data/data-lists";
|
||||
import { getLevelTotalExp } from "#data/exp";
|
||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
@ -11,7 +11,7 @@ import { Nature } from "#enums/nature";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
@ -218,12 +218,12 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
|
||||
|
||||
await doNewTeamPostProcess(transformations);
|
||||
setEncounterRewards({
|
||||
guaranteedModifierTypeFuncs: [
|
||||
modifierTypes.MEMORY_MUSHROOM,
|
||||
modifierTypes.ROGUE_BALL,
|
||||
modifierTypes.MINT,
|
||||
modifierTypes.MINT,
|
||||
modifierTypes.MINT,
|
||||
guaranteedRewardFuncs: [
|
||||
allRewards.MEMORY_MUSHROOM,
|
||||
allRewards.ROGUE_BALL,
|
||||
allRewards.MINT,
|
||||
allRewards.MINT,
|
||||
allRewards.MINT,
|
||||
],
|
||||
fillRemaining: false,
|
||||
});
|
||||
@ -242,7 +242,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
|
||||
],
|
||||
},
|
||||
async () => {
|
||||
// Battle your "future" team for some item rewards
|
||||
// Battle your "future" team for some item allRewards
|
||||
const transformations: PokemonTransformation[] =
|
||||
globalScene.currentBattle.mysteryEncounter!.misc.teamTransformations;
|
||||
|
||||
@ -293,7 +293,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
|
||||
};
|
||||
|
||||
const onBeforeRewards = () => {
|
||||
// Before battle rewards, unlock the passive on a pokemon in the player's team for the rest of the run (not permanently)
|
||||
// Before battle allRewards, unlock the passive on a pokemon in the player's team for the rest of the run (not permanently)
|
||||
// One random pokemon will get its passive unlocked
|
||||
const passiveDisabledPokemon = globalScene.getPlayerParty().filter(p => !p.passive);
|
||||
if (passiveDisabledPokemon?.length > 0) {
|
||||
@ -306,13 +306,13 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
|
||||
|
||||
setEncounterRewards(
|
||||
{
|
||||
guaranteedModifierTiers: [
|
||||
RewardTier.ROGUE,
|
||||
RewardTier.ROGUE,
|
||||
RewardTier.ULTRA,
|
||||
RewardTier.ULTRA,
|
||||
RewardTier.GREAT,
|
||||
RewardTier.GREAT,
|
||||
guaranteedRarityTiers: [
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.GREAT,
|
||||
RarityTier.GREAT,
|
||||
],
|
||||
fillRemaining: false,
|
||||
},
|
||||
|
@ -173,11 +173,11 @@ export class MysteryEncounter implements IMysteryEncounter {
|
||||
onVisualsStart?: () => boolean;
|
||||
/** Event triggered prior to {@linkcode CommandPhase}, during {@linkcode TurnInitPhase} */
|
||||
onTurnStart?: () => boolean;
|
||||
/** Event prior to any rewards logic in {@linkcode MysteryEncounterRewardsPhase} */
|
||||
/** Event prior to any allRewards logic in {@linkcode MysteryEncounterRewardsPhase} */
|
||||
onRewards?: () => Promise<void>;
|
||||
/** Will provide the player party EXP before rewards are displayed for that wave */
|
||||
/** Will provide the player party EXP before allRewards are displayed for that wave */
|
||||
doEncounterExp?: () => boolean;
|
||||
/** Will provide the player a rewards shop for that wave */
|
||||
/** Will provide the player a allRewards shop for that wave */
|
||||
doEncounterRewards?: () => boolean;
|
||||
/** Will execute callback during VictoryPhase of a continuousEncounter */
|
||||
doContinueEncounter?: () => Promise<void>;
|
||||
@ -237,10 +237,10 @@ export class MysteryEncounter implements IMysteryEncounter {
|
||||
encounterMode: MysteryEncounterMode;
|
||||
/**
|
||||
* Flag for checking if it's the first time a shop is being shown for an encounter.
|
||||
* Defaults to true so that the first shop does not override the specified rewards.
|
||||
* Defaults to true so that the first shop does not override the specified allRewards.
|
||||
* Will be set to false after a shop is shown (so can't reroll same rarity items for free)
|
||||
*/
|
||||
lockEncounterRewardTiers: boolean;
|
||||
lockEncounterRarityTiers: boolean;
|
||||
/**
|
||||
* Will be set automatically, indicates special moves in startOfBattleEffects are complete (so will not repeat)
|
||||
*/
|
||||
@ -295,7 +295,7 @@ export class MysteryEncounter implements IMysteryEncounter {
|
||||
|
||||
// Reset any dirty flags or encounter data
|
||||
this.startOfBattleEffectsComplete = false;
|
||||
this.lockEncounterRewardTiers = true;
|
||||
this.lockEncounterRarityTiers = true;
|
||||
this.dialogueTokens = {};
|
||||
this.enemyPartyConfigs = [];
|
||||
this.startOfBattleEffects = [];
|
||||
@ -561,7 +561,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
continuousEncounter = false;
|
||||
catchAllowed = false;
|
||||
fleeAllowed = true;
|
||||
lockEncounterRewardTiers = false;
|
||||
lockEncounterRarityTiers = false;
|
||||
startOfBattleEffectsComplete = false;
|
||||
hasBattleAnimationsWithoutTargets = false;
|
||||
skipEnemyBattleTurns = false;
|
||||
@ -928,13 +928,13 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Can set custom encounter rewards via this callback function
|
||||
* If rewards are always deterministic for an encounter, this is a good way to set them
|
||||
* Can set custom encounter allRewards via this callback function
|
||||
* If allRewards are always deterministic for an encounter, this is a good way to set them
|
||||
*
|
||||
* NOTE: If rewards are dependent on options selected, runtime data, etc.,
|
||||
* NOTE: If allRewards are dependent on options selected, runtime data, etc.,
|
||||
* It may be better to programmatically set doEncounterRewards elsewhere.
|
||||
* There is a helper function in mystery-encounter utils, setEncounterRewards(), which can be called programmatically to set rewards
|
||||
* @param doEncounterRewards Synchronous callback function to perform during rewards phase of the encounter
|
||||
* There is a helper function in mystery-encounter utils, setEncounterRewards(), which can be called programmatically to set allRewards
|
||||
* @param doEncounterRewards Synchronous callback function to perform during allRewards phase of the encounter
|
||||
* @returns
|
||||
*/
|
||||
withRewards(doEncounterRewards: () => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterRewards">> {
|
||||
@ -945,10 +945,10 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
||||
* Can set custom encounter exp via this callback function
|
||||
* If exp always deterministic for an encounter, this is a good way to set them
|
||||
*
|
||||
* NOTE: If rewards are dependent on options selected, runtime data, etc.,
|
||||
* NOTE: If allRewards are dependent on options selected, runtime data, etc.,
|
||||
* It may be better to programmatically set doEncounterExp elsewhere.
|
||||
* There is a helper function in mystery-encounter utils, setEncounterExp(), which can be called programmatically to set rewards
|
||||
* @param doEncounterExp Synchronous callback function to perform during rewards phase of the encounter
|
||||
* There is a helper function in mystery-encounter utils, setEncounterExp(), which can be called programmatically to set allRewards
|
||||
* @param doEncounterExp Synchronous callback function to perform during allRewards phase of the encounter
|
||||
* @returns
|
||||
*/
|
||||
withExp(doEncounterExp: () => boolean): this & Required<Pick<IMysteryEncounter, "doEncounterExp">> {
|
||||
|
@ -5,7 +5,6 @@ import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { BiomePoolTier, biomeLinks } from "#balance/biomes";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "#data/battle-anims";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import type { IEggOptions } from "#data/egg";
|
||||
import { Egg } from "#data/egg";
|
||||
import type { Gender } from "#data/gender";
|
||||
@ -17,7 +16,6 @@ import type { AiType } from "#enums/ai-type";
|
||||
import type { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
import { FieldPosition } from "#enums/field-position";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import type { Nature } from "#enums/nature";
|
||||
@ -31,8 +29,7 @@ import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import { EnemyPokemon } from "#field/pokemon";
|
||||
import { Trainer } from "#field/trainer";
|
||||
import type { HeldItemConfiguration } from "#items/held-item-data-types";
|
||||
import type { CustomModifierSettings, ModifierType } from "#modifiers/modifier-type";
|
||||
import { getPartyLuckValue, ModifierTypeGenerator, ModifierTypeOption } from "#modifiers/modifier-type";
|
||||
import type { CustomRewardSettings } from "#items/reward-pool-utils";
|
||||
import { PokemonMove } from "#moves/pokemon-move";
|
||||
import { showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||
import type { MysteryEncounterOption } from "#mystery-encounters/mystery-encounter-option";
|
||||
@ -44,6 +41,7 @@ import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstact-option-se
|
||||
import type { PartyOption, PokemonSelectFilter } from "#ui/party-ui-handler";
|
||||
import { PartyUiMode } from "#ui/party-ui-handler";
|
||||
import { coerceArray, isNullOrUndefined, randomString, randSeedInt, randSeedItem } from "#utils/common";
|
||||
import { getPartyLuckValue } from "#utils/party";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
import i18next from "i18next";
|
||||
|
||||
@ -474,45 +472,6 @@ export function updatePlayerMoney(changeValue: number, playSound = true, showMes
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts modifier bullshit to an actual item
|
||||
* @param modifier
|
||||
* @param pregenArgs Can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
||||
*/
|
||||
export function generateModifierType(modifier: () => ModifierType, pregenArgs?: any[]): ModifierType | null {
|
||||
const modifierId = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifier);
|
||||
if (!modifierId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let result: ModifierType = modifierTypes[modifierId]();
|
||||
|
||||
// Populates item id and tier (order matters)
|
||||
result = result
|
||||
.withIdFromFunc(modifierTypes[modifierId])
|
||||
.withTierFromPool(ModifierPoolType.PLAYER, globalScene.getPlayerParty());
|
||||
|
||||
return result instanceof ModifierTypeGenerator
|
||||
? result.generateType(globalScene.getPlayerParty(), pregenArgs)
|
||||
: result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts modifier bullshit to an actual item
|
||||
* @param modifier
|
||||
* @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
||||
*/
|
||||
export function generateModifierTypeOption(
|
||||
modifier: () => ModifierType,
|
||||
pregenArgs?: any[],
|
||||
): ModifierTypeOption | null {
|
||||
const result = generateModifierType(modifier, pregenArgs);
|
||||
if (result) {
|
||||
return new ModifierTypeOption(result, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is intended for use inside onPreOptionPhase() of an encounter option
|
||||
* @param onPokemonSelected - Any logic that needs to be performed when Pokemon is chosen
|
||||
@ -727,12 +686,12 @@ export function selectOptionThenPokemon(
|
||||
/**
|
||||
* Will initialize reward phases to follow the mystery encounter
|
||||
* Can have shop displayed or skipped
|
||||
* @param customShopRewards - adds a shop phase with the specified rewards / reward tiers
|
||||
* @param customShopRewards - adds a shop phase with the specified allRewards / reward tiers
|
||||
* @param eggRewards
|
||||
* @param preRewardsCallback - can execute an arbitrary callback before the new phases if necessary (useful for updating items/party/injecting new phases before {@linkcode MysteryEncounterRewardsPhase})
|
||||
*/
|
||||
export function setEncounterRewards(
|
||||
customShopRewards?: CustomModifierSettings,
|
||||
customShopRewards?: CustomRewardSettings,
|
||||
eggRewards?: IEggOptions[],
|
||||
preRewardsCallback?: Function,
|
||||
) {
|
||||
@ -809,8 +768,8 @@ export function initSubsequentOptionSelect(optionSelectSettings: OptionSelectSet
|
||||
|
||||
/**
|
||||
* Can be used to exit an encounter without any battles or followup
|
||||
* Will skip any shops and rewards, and queue the next encounter phase as normal
|
||||
* @param addHealPhase - when true, will add a shop phase to end of encounter with 0 rewards but healing items are available
|
||||
* Will skip any shops and allRewards, and queue the next encounter phase as normal
|
||||
* @param addHealPhase - when true, will add a shop phase to end of encounter with 0 allRewards but healing items are available
|
||||
* @param encounterMode - Can set custom encounter mode if necessary (may be required for forcing Pokemon to return before next phase)
|
||||
*/
|
||||
export function leaveEncounterWithoutBattle(
|
||||
|
@ -4,8 +4,8 @@ import { globalScene } from "#app/global-scene";
|
||||
import { randSeedInt } from "#app/utils/common";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { TrainerVariant } from "#enums/trainer-variant";
|
||||
|
||||
@ -45,8 +45,8 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||
),
|
||||
)
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT],
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [RarityTier.ULTRA, RarityTier.GREAT, RarityTier.GREAT],
|
||||
allowLuckUpgrades: false,
|
||||
}),
|
||||
[ClassicFixedBossWaves.EVIL_GRUNT_1]: new FixedBattleConfig()
|
||||
@ -77,8 +77,8 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||
),
|
||||
)
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT],
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [RarityTier.ULTRA, RarityTier.ULTRA, RarityTier.GREAT, RarityTier.GREAT],
|
||||
allowLuckUpgrades: false,
|
||||
}),
|
||||
[ClassicFixedBossWaves.EVIL_GRUNT_2]: new FixedBattleConfig()
|
||||
@ -150,8 +150,8 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||
),
|
||||
)
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA],
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [RarityTier.ULTRA, RarityTier.ULTRA, RarityTier.ULTRA, RarityTier.ULTRA],
|
||||
allowLuckUpgrades: false,
|
||||
}),
|
||||
[ClassicFixedBossWaves.EVIL_GRUNT_4]: new FixedBattleConfig()
|
||||
@ -212,14 +212,8 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
TrainerType.PENNY,
|
||||
]),
|
||||
)
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.ULTRA,
|
||||
],
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ROGUE, RarityTier.ULTRA, RarityTier.ULTRA, RarityTier.ULTRA],
|
||||
allowLuckUpgrades: false,
|
||||
}),
|
||||
[ClassicFixedBossWaves.RIVAL_5]: new FixedBattleConfig()
|
||||
@ -231,14 +225,8 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||
),
|
||||
)
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.ULTRA,
|
||||
],
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ROGUE, RarityTier.ROGUE, RarityTier.ULTRA, RarityTier.ULTRA],
|
||||
allowLuckUpgrades: false,
|
||||
}),
|
||||
[ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig()
|
||||
@ -258,14 +246,14 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
TrainerType.PENNY_2,
|
||||
]),
|
||||
)
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.ULTRA,
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
],
|
||||
allowLuckUpgrades: false,
|
||||
}),
|
||||
@ -362,14 +350,14 @@ export const classicFixedBattles: FixedBattleConfigs = {
|
||||
globalScene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT,
|
||||
),
|
||||
)
|
||||
.setCustomModifierRewards({
|
||||
guaranteedModifierTiers: [
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ROGUE,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.ULTRA,
|
||||
ModifierTier.GREAT,
|
||||
ModifierTier.GREAT,
|
||||
.setCustomRewards({
|
||||
guaranteedRarityTiers: [
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ROGUE,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.ULTRA,
|
||||
RarityTier.GREAT,
|
||||
RarityTier.GREAT,
|
||||
],
|
||||
allowLuckUpgrades: false,
|
||||
}),
|
||||
|
@ -3,7 +3,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { pokemonEvolutions, pokemonPrevolutions } from "#balance/pokemon-evolutions";
|
||||
import { signatureSpecies } from "#balance/signature-species";
|
||||
import { tmSpecies } from "#balance/tms";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { doubleBattleDialogue } from "#data/double-battle-dialogue";
|
||||
import { Gender } from "#data/gender";
|
||||
import type { PokemonSpecies, PokemonSpeciesFilter } from "#data/pokemon-species";
|
||||
@ -31,7 +31,7 @@ import {
|
||||
TrainerPartyTemplate,
|
||||
trainerPartyTemplates,
|
||||
} from "#trainers/trainer-party-template";
|
||||
import type { ModifierTypeFunc } from "#types/modifier-types";
|
||||
import type { RewardFunc } from "#types/rewards";
|
||||
import type {
|
||||
GenAIFunc,
|
||||
GenTrainerItemsFunc,
|
||||
@ -113,9 +113,9 @@ export class TrainerConfig {
|
||||
public femaleEncounterBgm: string;
|
||||
public doubleEncounterBgm: string;
|
||||
public victoryBgm: string;
|
||||
public genModifiersFunc: GenTrainerItemsFunc;
|
||||
public genTrainerItemsFunc: GenTrainerItemsFunc;
|
||||
public genAIFuncs: GenAIFunc[] = [];
|
||||
public modifierRewardFuncs: ModifierTypeFunc[] = [];
|
||||
public rewardFuncs: RewardFunc[] = [];
|
||||
public partyTemplates: TrainerPartyTemplate[];
|
||||
public partyTemplateFunc: PartyTemplateFunc;
|
||||
public partyMemberFuncs: PartyMemberFuncs = {};
|
||||
@ -465,8 +465,8 @@ export class TrainerConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
setGenModifiersFunc(genModifiersFunc: GenTrainerItemsFunc): TrainerConfig {
|
||||
this.genModifiersFunc = genModifiersFunc;
|
||||
setGenTrainerItemsFunc(genTrainerItemsFunc: GenTrainerItemsFunc): TrainerConfig {
|
||||
this.genTrainerItemsFunc = genTrainerItemsFunc;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ export class TrainerConfig {
|
||||
* @param slot Optional, a specified slot that should be terastallized. Wraps to match party size (-1 will get the last slot and so on).
|
||||
* @returns this
|
||||
*/
|
||||
setRandomTeraModifiers(count: () => number, slot?: number): TrainerConfig {
|
||||
setRandomTeraType(count: () => number, slot?: number): TrainerConfig {
|
||||
this.genAIFuncs.push((party: EnemyPokemon[]) => {
|
||||
const shedinjaCanTera = !this.hasSpecialtyType() || this.specialtyType === PokemonType.BUG; // Better to check one time than 6
|
||||
const partyMemberIndexes = new Array(party.length)
|
||||
@ -507,23 +507,11 @@ export class TrainerConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
// function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: Type[]): PersistentModifier[] {
|
||||
// const ret: PersistentModifier[] = [];
|
||||
// const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i);
|
||||
// for (let t = 0; t < Math.min(count, party.length); t++) {
|
||||
// const randomIndex = Utils.randSeedItem(partyMemberIndexes);
|
||||
// partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1);
|
||||
// ret.push(modifierTypes.TERA_SHARD().generateType([], [ Utils.randSeedItem(types ? types : party[randomIndex].getTypes()) ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct?
|
||||
// }
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
setModifierRewardFuncs(...modifierTypeFuncs: (() => ModifierTypeFunc)[]): TrainerConfig {
|
||||
this.modifierRewardFuncs = modifierTypeFuncs.map(func => () => {
|
||||
const modifierTypeFunc = func();
|
||||
const modifierType = modifierTypeFunc();
|
||||
modifierType.withIdFromFunc(modifierTypeFunc);
|
||||
return modifierType;
|
||||
setRewardFuncs(...rewardFuncs: (() => RewardFunc)[]): TrainerConfig {
|
||||
this.rewardFuncs = rewardFuncs.map(func => () => {
|
||||
const rewardFunc = func();
|
||||
const reward = rewardFunc();
|
||||
return reward;
|
||||
});
|
||||
return this;
|
||||
}
|
||||
@ -689,7 +677,7 @@ export class TrainerConfig {
|
||||
this.setHasVoucher(true);
|
||||
this.setBattleBgm("battle_unova_gym");
|
||||
this.setVictoryBgm("victory_gym");
|
||||
this.setRandomTeraModifiers(
|
||||
this.setRandomTeraType(
|
||||
() => (ignoreMinTeraWave || globalScene.currentBattle.waveIndex >= GYM_LEADER_TERA_WAVE ? 1 : 0),
|
||||
teraSlot,
|
||||
);
|
||||
@ -750,7 +738,7 @@ export class TrainerConfig {
|
||||
this.setHasVoucher(true);
|
||||
this.setBattleBgm("battle_unova_elite");
|
||||
this.setVictoryBgm("victory_gym");
|
||||
this.setRandomTeraModifiers(() => 1, teraSlot);
|
||||
this.setRandomTeraType(() => 1, teraSlot);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -927,11 +915,11 @@ export class TrainerConfig {
|
||||
clone = this.battleBgm ? clone.setBattleBgm(this.battleBgm) : clone;
|
||||
clone = this.encounterBgm ? clone.setEncounterBgm(this.encounterBgm) : clone;
|
||||
clone = this.victoryBgm ? clone.setVictoryBgm(this.victoryBgm) : clone;
|
||||
clone = this.genModifiersFunc ? clone.setGenModifiersFunc(this.genModifiersFunc) : clone;
|
||||
clone = this.genTrainerItemsFunc ? clone.setGenTrainerItemsFunc(this.genTrainerItemsFunc) : clone;
|
||||
|
||||
if (this.modifierRewardFuncs) {
|
||||
if (this.rewardFuncs) {
|
||||
// Clones array instead of passing ref
|
||||
clone.modifierRewardFuncs = this.modifierRewardFuncs.slice(0);
|
||||
clone.rewardFuncs = this.rewardFuncs.slice(0);
|
||||
}
|
||||
|
||||
if (this.partyTemplates) {
|
||||
@ -4443,9 +4431,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setBattleBgm("battle_rival")
|
||||
.setMixedBattleBgm("battle_rival")
|
||||
.setPartyTemplates(trainerPartyTemplates.RIVAL)
|
||||
.setModifierRewardFuncs(
|
||||
() => modifierTypes.SUPER_EXP_CHARM,
|
||||
() => modifierTypes.EXP_SHARE,
|
||||
.setRewardFuncs(
|
||||
() => allRewards.SUPER_EXP_CHARM,
|
||||
() => allRewards.EXP_SHARE,
|
||||
)
|
||||
.setPartyMemberFunc(
|
||||
0,
|
||||
@ -4513,7 +4501,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setBattleBgm("battle_rival")
|
||||
.setMixedBattleBgm("battle_rival")
|
||||
.setPartyTemplates(trainerPartyTemplates.RIVAL_2)
|
||||
.setModifierRewardFuncs(() => modifierTypes.EXP_SHARE)
|
||||
.setRewardFuncs(() => allRewards.EXP_SHARE)
|
||||
.setPartyMemberFunc(
|
||||
0,
|
||||
getRandomPartyMemberFunc(
|
||||
@ -4666,7 +4654,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setBattleBgm("battle_rival_2")
|
||||
.setMixedBattleBgm("battle_rival_2")
|
||||
.setPartyTemplates(trainerPartyTemplates.RIVAL_4)
|
||||
.setModifierRewardFuncs(() => modifierTypes.TERA_ORB)
|
||||
.setRewardFuncs(() => allRewards.TERA_ORB)
|
||||
.setPartyMemberFunc(
|
||||
0,
|
||||
getRandomPartyMemberFunc(
|
||||
|
37
src/enums/held-item-effect.ts
Normal file
37
src/enums/held-item-effect.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import type { EnumValues } from "#types/enum-types";
|
||||
|
||||
/**
|
||||
* Enum representing the various "classes" of item effects that can be applied.
|
||||
*/
|
||||
export const HeldItemEffect = {
|
||||
ATTACK_TYPE_BOOST: 1,
|
||||
TURN_END_HEAL: 2,
|
||||
HIT_HEAL: 3,
|
||||
RESET_NEGATIVE_STAT_STAGE: 4,
|
||||
EXP_BOOSTER: 5,
|
||||
// Should we actually distinguish different berry effects?
|
||||
BERRY: 6,
|
||||
BASE_STAT_BOOSTER: 7,
|
||||
INSTANT_REVIVE: 8,
|
||||
STAT_BOOST: 9,
|
||||
CRIT_BOOST: 10,
|
||||
TURN_END_STATUS: 11,
|
||||
SURVIVE_CHANCE: 12,
|
||||
BYPASS_SPEED_CHANCE: 13,
|
||||
FLINCH_CHANCE: 14,
|
||||
FIELD_EFFECT: 15,
|
||||
FRIENDSHIP_BOOSTER: 16,
|
||||
NATURE_WEIGHT_BOOSTER: 17,
|
||||
ACCURACY_BOOSTER: 18,
|
||||
MULTI_HIT: 19,
|
||||
DAMAGE_MONEY_REWARD: 20,
|
||||
BATON: 21,
|
||||
TURN_END_ITEM_STEAL: 22,
|
||||
CONTACT_ITEM_STEAL_CHANCE: 23,
|
||||
EVO_TRACKER: 40,
|
||||
BASE_STAT_TOTAL: 50,
|
||||
BASE_STAT_FLAT: 51,
|
||||
INCREMENTING_STAT: 52,
|
||||
} as const;
|
||||
|
||||
export type HeldItemEffect = EnumValues<typeof HeldItemEffect>;
|
@ -1,3 +1,5 @@
|
||||
import type { EnumValues } from "#types/enum-types";
|
||||
|
||||
// TODO: make category the lower 2 bytes
|
||||
export const HeldItemId = {
|
||||
NONE: 0x0000,
|
||||
@ -92,19 +94,24 @@ export const HeldItemId = {
|
||||
GIMMIGHOUL_EVO_TRACKER: 0x0A01,
|
||||
} as const;
|
||||
|
||||
export type HeldItemId = (typeof HeldItemId)[keyof typeof HeldItemId];
|
||||
export type HeldItemId = EnumValues<typeof HeldItemId>;
|
||||
|
||||
type HeldItemNameMap = {
|
||||
[k in HeldItemName as (typeof HeldItemId)[k]]: k
|
||||
}
|
||||
|
||||
type HeldItemName = keyof typeof HeldItemId;
|
||||
type HeldItemValue = typeof HeldItemId[HeldItemName]; // equivalent to `HeldItemId`
|
||||
|
||||
// Use a type-safe reducer to force number keys and values
|
||||
export const HeldItemNames: Record<HeldItemValue, HeldItemName> = Object.entries(HeldItemId).reduce(
|
||||
/** `const object` mapping all held item IDs to their respective names. */
|
||||
// TODO: This stores names as UPPER_SNAKE_CASE, but the locales are in PascalCase...
|
||||
export const HeldItemNames = Object.freeze(Object.entries(HeldItemId).reduce(
|
||||
// Use a type-safe reducer to force number keys and values
|
||||
(acc, [key, value]) => {
|
||||
acc[value as HeldItemValue] = key as HeldItemName;
|
||||
acc[value] = key;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<HeldItemValue, HeldItemName>
|
||||
);
|
||||
{}
|
||||
)) as HeldItemNameMap;
|
||||
|
||||
export const HeldItemCategoryId = {
|
||||
NONE: 0x0000,
|
||||
@ -120,7 +127,7 @@ export const HeldItemCategoryId = {
|
||||
EVO_TRACKER: 0x0A00,
|
||||
} as const;
|
||||
|
||||
export type HeldItemCategoryId = (typeof HeldItemCategoryId)[keyof typeof HeldItemCategoryId];
|
||||
export type HeldItemCategoryId = EnumValues<typeof HeldItemCategoryId>;
|
||||
|
||||
const ITEM_CATEGORY_MASK = 0xFF00
|
||||
|
||||
|
99
src/enums/reward-id.ts
Normal file
99
src/enums/reward-id.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import type { EnumValues } from "#types/enum-types";
|
||||
|
||||
export const RewardId = {
|
||||
NONE: 0x0000,
|
||||
|
||||
POKEBALL: 0x2001,
|
||||
GREAT_BALL: 0x2002,
|
||||
ULTRA_BALL: 0x2003,
|
||||
ROGUE_BALL: 0x2004,
|
||||
MASTER_BALL: 0x2005,
|
||||
|
||||
VOUCHER: 0x2101,
|
||||
VOUCHER_PLUS: 0x2102,
|
||||
VOUCHER_PREMIUM: 0x2103,
|
||||
|
||||
NUGGET: 0x2201,
|
||||
BIG_NUGGET: 0x2202,
|
||||
RELIC_GOLD: 0x2203,
|
||||
|
||||
RARE_CANDY: 0x2301,
|
||||
RARER_CANDY: 0x2302,
|
||||
|
||||
EVOLUTION_ITEM: 0x2401,
|
||||
RARE_EVOLUTION_ITEM: 0x2402,
|
||||
|
||||
POTION: 0x2501,
|
||||
SUPER_POTION: 0x2502,
|
||||
HYPER_POTION: 0x2503,
|
||||
MAX_POTION: 0x2504,
|
||||
FULL_HEAL: 0x2505,
|
||||
FULL_RESTORE: 0x2506,
|
||||
|
||||
REVIVE: 0x2601,
|
||||
MAX_REVIVE: 0x2602,
|
||||
SACRED_ASH: 0x2603,
|
||||
|
||||
ETHER: 0x2701,
|
||||
MAX_ETHER: 0x2702,
|
||||
|
||||
ELIXIR: 0x2801,
|
||||
MAX_ELIXIR: 0x2802,
|
||||
|
||||
PP_UP: 0x2901,
|
||||
PP_MAX: 0x2902,
|
||||
|
||||
TM_COMMON: 0x2A01,
|
||||
TM_GREAT: 0x2A02,
|
||||
TM_ULTRA: 0x2A03,
|
||||
|
||||
MINT: 0x2B01,
|
||||
TERA_SHARD: 0x2B02,
|
||||
MEMORY_MUSHROOM: 0x2B03,
|
||||
DNA_SPLICERS: 0x2B04,
|
||||
|
||||
HELD_ITEM: 0x2C01,
|
||||
SPECIES_STAT_BOOSTER: 0x2C02,
|
||||
RARE_SPECIES_STAT_BOOSTER: 0x2C03,
|
||||
BASE_STAT_BOOSTER: 0x2C04,
|
||||
ATTACK_TYPE_BOOSTER: 0x2C05,
|
||||
BERRY: 0x2C06,
|
||||
|
||||
TRAINER_ITEM: 0x2D01,
|
||||
TEMP_STAT_STAGE_BOOSTER: 0x2D02,
|
||||
LURE: 0x2D03,
|
||||
SUPER_LURE: 0x2D04,
|
||||
MAX_LURE: 0x2D05,
|
||||
|
||||
FORM_CHANGE_ITEM: 0x2E01,
|
||||
RARE_FORM_CHANGE_ITEM: 0x2E02,
|
||||
} as const;
|
||||
|
||||
export type RewardId = EnumValues<typeof RewardId>;
|
||||
|
||||
export const RewardCategoryId = {
|
||||
NONE: 0x0000,
|
||||
POKEBALL: 0x0100,
|
||||
VOUCHER: 0x0200,
|
||||
MONEY: 0x0300,
|
||||
CANDY: 0x0400,
|
||||
EVOLUTION_ITEM: 0x0500,
|
||||
HEALING: 0x0600,
|
||||
REVIVE: 0x0700,
|
||||
ETHER: 0x0800,
|
||||
ELIXIR: 0x0900,
|
||||
PP_UP: 0x0A00,
|
||||
TM: 0x0B00,
|
||||
OTHER: 0x0C00,
|
||||
HELD_ITEM: 0x0D00,
|
||||
TRAINER_ITEM: 0x0E00,
|
||||
FORM_CHANGE_ITEM: 0x0F00,
|
||||
} as const;
|
||||
|
||||
export type RewardCategoryId = EnumValues<typeof RewardCategoryId>;
|
||||
|
||||
const ITEM_CATEGORY_MASK = 0xFF00
|
||||
|
||||
export function getRewardCategory(itemId: RewardId): RewardCategoryId {
|
||||
return (itemId & ITEM_CATEGORY_MASK) as RewardCategoryId;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
export enum ModifierPoolType {
|
||||
export enum RewardPoolType {
|
||||
PLAYER,
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export enum RewardTier {
|
||||
export enum RarityTier {
|
||||
COMMON,
|
||||
GREAT,
|
||||
ULTRA,
|
||||
|
@ -1,56 +1,56 @@
|
||||
export const TrainerItemId = {
|
||||
NONE: 0x0000,
|
||||
|
||||
MAP: 0x0B01,
|
||||
IV_SCANNER: 0x0B02,
|
||||
LOCK_CAPSULE: 0x0B03,
|
||||
MEGA_BRACELET: 0x0B04,
|
||||
DYNAMAX_BAND: 0x0B05,
|
||||
TERA_ORB: 0x0B06,
|
||||
MAP: 0x1001,
|
||||
IV_SCANNER: 0x1002,
|
||||
LOCK_CAPSULE: 0x1003,
|
||||
MEGA_BRACELET: 0x1004,
|
||||
DYNAMAX_BAND: 0x1005,
|
||||
TERA_ORB: 0x1006,
|
||||
|
||||
GOLDEN_POKEBALL: 0x0B07,
|
||||
GOLDEN_POKEBALL: 0x1007,
|
||||
|
||||
OVAL_CHARM: 0x0B08,
|
||||
EXP_SHARE: 0x0B09,
|
||||
EXP_BALANCE: 0x0B0A,
|
||||
OVAL_CHARM: 0x1008,
|
||||
EXP_SHARE: 0x1009,
|
||||
EXP_BALANCE: 0x100A,
|
||||
|
||||
CANDY_JAR: 0x0B0B,
|
||||
BERRY_POUCH: 0x0B0C,
|
||||
CANDY_JAR: 0x100B,
|
||||
BERRY_POUCH: 0x100C,
|
||||
|
||||
HEALING_CHARM: 0x0B0D,
|
||||
EXP_CHARM: 0x0B0E,
|
||||
SUPER_EXP_CHARM: 0x0B0F,
|
||||
GOLDEN_EXP_CHARM: 0x0B10,
|
||||
AMULET_COIN: 0x0B11,
|
||||
HEALING_CHARM: 0x100D,
|
||||
EXP_CHARM: 0x100E,
|
||||
SUPER_EXP_CHARM: 0x100F,
|
||||
GOLDEN_EXP_CHARM: 0x1010,
|
||||
AMULET_COIN: 0x1011,
|
||||
|
||||
ABILITY_CHARM: 0x0B12,
|
||||
SHINY_CHARM: 0x0B13,
|
||||
CATCHING_CHARM: 0x0B14,
|
||||
ABILITY_CHARM: 0x1012,
|
||||
SHINY_CHARM: 0x1013,
|
||||
CATCHING_CHARM: 0x1014,
|
||||
|
||||
BLACK_SLUDGE: 0x0B15,
|
||||
GOLDEN_BUG_NET: 0x0B16,
|
||||
BLACK_SLUDGE: 0x1015,
|
||||
GOLDEN_BUG_NET: 0x1016,
|
||||
|
||||
LURE: 0x0C01,
|
||||
SUPER_LURE: 0x0C02,
|
||||
MAX_LURE: 0x0C03,
|
||||
LURE: 0x1101,
|
||||
SUPER_LURE: 0x1102,
|
||||
MAX_LURE: 0x1103,
|
||||
|
||||
X_ATTACK: 0x0D01,
|
||||
X_DEFENSE: 0x0D02,
|
||||
X_SP_ATK: 0x0D03,
|
||||
X_SP_DEF: 0x0D04,
|
||||
X_SPEED: 0x0D05,
|
||||
X_ACCURACY: 0x0D06,
|
||||
DIRE_HIT: 0x0D07,
|
||||
X_ATTACK: 0x1201,
|
||||
X_DEFENSE: 0x1202,
|
||||
X_SP_ATK: 0x1203,
|
||||
X_SP_DEF: 0x1204,
|
||||
X_SPEED: 0x1205,
|
||||
X_ACCURACY: 0x1206,
|
||||
DIRE_HIT: 0x1207,
|
||||
|
||||
ENEMY_DAMAGE_BOOSTER: 0x0E01,
|
||||
ENEMY_DAMAGE_REDUCTION: 0x0E02,
|
||||
ENEMY_HEAL: 0x0E03,
|
||||
ENEMY_ATTACK_POISON_CHANCE: 0x0E04,
|
||||
ENEMY_ATTACK_PARALYZE_CHANCE: 0x0E05,
|
||||
ENEMY_ATTACK_BURN_CHANCE: 0x0E06,
|
||||
ENEMY_STATUS_EFFECT_HEAL_CHANCE: 0x0E07,
|
||||
ENEMY_ENDURE_CHANCE: 0x0E08,
|
||||
ENEMY_FUSED_CHANCE: 0x0E09,
|
||||
ENEMY_DAMAGE_BOOSTER: 0x1301,
|
||||
ENEMY_DAMAGE_REDUCTION: 0x1302,
|
||||
ENEMY_HEAL: 0x1303,
|
||||
ENEMY_ATTACK_POISON_CHANCE: 0x1304,
|
||||
ENEMY_ATTACK_PARALYZE_CHANCE: 0x1305,
|
||||
ENEMY_ATTACK_BURN_CHANCE: 0x1306,
|
||||
ENEMY_STATUS_EFFECT_HEAL_CHANCE: 0x1307,
|
||||
ENEMY_ENDURE_CHANCE: 0x1308,
|
||||
ENEMY_FUSED_CHANCE: 0x1309,
|
||||
} as const;
|
||||
|
||||
export type TrainerItemId = (typeof TrainerItemId)[keyof typeof TrainerItemId];
|
||||
|
@ -5,7 +5,7 @@ export enum UiMode {
|
||||
FIGHT,
|
||||
BALL,
|
||||
TARGET_SELECT,
|
||||
MODIFIER_SELECT,
|
||||
REWARD_SELECT,
|
||||
SAVE_SLOT,
|
||||
PARTY,
|
||||
SUMMARY,
|
||||
|
@ -19,6 +19,7 @@ import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||
import type { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { CommonAnim } from "#enums/move-anims-common";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import type { PokemonType } from "#enums/pokemon-type";
|
||||
@ -29,7 +30,6 @@ import { WeatherType } from "#enums/weather-type";
|
||||
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#events/arena";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { applyHeldItems } from "#items/all-held-items";
|
||||
import { HeldItemEffect } from "#items/held-item";
|
||||
import type { Move } from "#moves/move";
|
||||
import type { AbstractConstructor } from "#types/type-helpers";
|
||||
import { type Constructor, isNullOrUndefined, NumberHolder, randSeedInt } from "#utils/common";
|
||||
|
@ -80,6 +80,7 @@ import { ChallengeType } from "#enums/challenge-type";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { DexAttr } from "#enums/dex-attr";
|
||||
import { FieldPosition } from "#enums/field-position";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import { HitResult } from "#enums/hit-result";
|
||||
import { LearnMoveSituation } from "#enums/learn-move-situation";
|
||||
@ -92,7 +93,7 @@ import { Nature } from "#enums/nature";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import {
|
||||
@ -111,7 +112,6 @@ import { UiMode } from "#enums/ui-mode";
|
||||
import { WeatherType } from "#enums/weather-type";
|
||||
import { doShinySparkleAnim } from "#field/anims";
|
||||
import { applyHeldItems } from "#items/all-held-items";
|
||||
import { HeldItemEffect } from "#items/held-item";
|
||||
import type { HeldItemConfiguration } from "#items/held-item-data-types";
|
||||
import { HeldItemManager } from "#items/held-item-manager";
|
||||
import { assignItemsFromConfiguration } from "#items/held-item-pool";
|
||||
@ -2882,13 +2882,13 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*
|
||||
* The base shiny odds are {@linkcode BASE_SHINY_CHANCE} / `65536`
|
||||
* @param thresholdOverride number that is divided by `2^16` (`65536`) to get the shiny chance, overrides {@linkcode shinyThreshold} if set (bypassing shiny rate modifiers such as Shiny Charm)
|
||||
* @param applyModifiersToOverride If {@linkcode thresholdOverride} is set and this is true, will apply Shiny Charm and event modifiers to {@linkcode thresholdOverride}
|
||||
* @param applyItemsToOverride If {@linkcode thresholdOverride} is set and this is true, will apply Shiny Charm and event modifiers to {@linkcode thresholdOverride}
|
||||
* @returns `true` if the Pokemon has been set as a shiny, `false` otherwise
|
||||
*/
|
||||
public trySetShinySeed(thresholdOverride?: number, applyModifiersToOverride?: boolean): boolean {
|
||||
public trySetShinySeed(thresholdOverride?: number, applyItemsToOverride?: boolean): boolean {
|
||||
if (!this.shiny) {
|
||||
const shinyThreshold = new NumberHolder(thresholdOverride ?? BASE_SHINY_CHANCE);
|
||||
if (applyModifiersToOverride) {
|
||||
if (applyItemsToOverride) {
|
||||
if (timedEventManager.isEventActive()) {
|
||||
shinyThreshold.value *= timedEventManager.getShinyMultiplier();
|
||||
}
|
||||
@ -2954,15 +2954,15 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*
|
||||
* The base hidden ability odds are {@linkcode BASE_HIDDEN_ABILITY_CHANCE} / `65536`
|
||||
* @param thresholdOverride number that is divided by `2^16` (`65536`) to get the HA chance, overrides {@linkcode haThreshold} if set (bypassing HA rate modifiers such as Ability Charm)
|
||||
* @param applyModifiersToOverride If {@linkcode thresholdOverride} is set and this is true, will apply Ability Charm to {@linkcode thresholdOverride}
|
||||
* @param applyItemsToOverride If {@linkcode thresholdOverride} is set and this is true, will apply Ability Charm to {@linkcode thresholdOverride}
|
||||
* @returns `true` if the Pokemon has been set to have its hidden ability, `false` otherwise
|
||||
*/
|
||||
public tryRerollHiddenAbilitySeed(thresholdOverride?: number, applyModifiersToOverride?: boolean): boolean {
|
||||
public tryRerollHiddenAbilitySeed(thresholdOverride?: number, applyItemsToOverride?: boolean): boolean {
|
||||
if (!this.species.abilityHidden) {
|
||||
return false;
|
||||
}
|
||||
const haThreshold = new NumberHolder(thresholdOverride ?? BASE_HIDDEN_ABILITY_CHANCE);
|
||||
if (applyModifiersToOverride) {
|
||||
if (applyItemsToOverride) {
|
||||
if (!this.hasTrainer()) {
|
||||
globalScene.applyPlayerItems(TrainerItemEffect.HIDDEN_ABILITY_CHANCE_BOOSTER, { numberHolder: haThreshold });
|
||||
}
|
||||
@ -3108,11 +3108,11 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
if (compatible && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)")) {
|
||||
if (tmPoolTiers[moveId] === RewardTier.COMMON && this.level >= 15) {
|
||||
if (tmPoolTiers[moveId] === RarityTier.COMMON && this.level >= 15) {
|
||||
movePool.push([moveId, 4]);
|
||||
} else if (tmPoolTiers[moveId] === RewardTier.GREAT && this.level >= 30) {
|
||||
} else if (tmPoolTiers[moveId] === RarityTier.GREAT && this.level >= 30) {
|
||||
movePool.push([moveId, 8]);
|
||||
} else if (tmPoolTiers[moveId] === RewardTier.ULTRA && this.level >= 50) {
|
||||
} else if (tmPoolTiers[moveId] === RarityTier.ULTRA && this.level >= 50) {
|
||||
movePool.push([moveId, 14]);
|
||||
}
|
||||
}
|
||||
|
@ -634,7 +634,7 @@ export class Trainer extends Phaser.GameObjects.Container {
|
||||
return maxScorePartyMemberIndexes[0];
|
||||
}
|
||||
|
||||
getPartyMemberModifierChanceMultiplier(index: number): number {
|
||||
getPartyMemberItemChanceMultiplier(index: number): number {
|
||||
switch (this.getPartyTemplate().getStrength(index)) {
|
||||
case PartyMemberStrength.WEAKER:
|
||||
return 0.75;
|
||||
@ -647,14 +647,14 @@ export class Trainer extends Phaser.GameObjects.Container {
|
||||
case PartyMemberStrength.STRONGER:
|
||||
return 0.375;
|
||||
default:
|
||||
console.warn("getPartyMemberModifierChanceMultiplier not defined. Using default 0");
|
||||
console.warn("getPartyMemberItemChanceMultiplier not defined. Using default 0");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
genTrainerItems(party: EnemyPokemon[]): TrainerItemConfiguration {
|
||||
if (this.config.genModifiersFunc) {
|
||||
return this.config.genModifiersFunc(party);
|
||||
if (this.config.genTrainerItemsFunc) {
|
||||
return this.config.genTrainerItemsFunc(party);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ export class GameMode implements GameModeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
getEnemyModifierChance(isBoss: boolean): number {
|
||||
getEnemyItemChance(isBoss: boolean): number {
|
||||
switch (this.modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
|
@ -24,7 +24,6 @@ import { ExpBoosterHeldItem, type ExpBoostParams } from "#items/exp-booster";
|
||||
import { FieldEffectHeldItem, type FieldEffectParams } from "#items/field-effect";
|
||||
import { FlinchChanceHeldItem, type FlinchChanceParams } from "#items/flinch-chance";
|
||||
import { FriendshipBoosterHeldItem, type FriendshipBoostParams } from "#items/friendship-booster";
|
||||
import { HeldItemEffect } from "#items/held-item";
|
||||
import { HitHealHeldItem, type HitHealParams } from "#items/hit-heal";
|
||||
import { IncrementingStatHeldItem, type IncrementingStatParams } from "#items/incrementing-stat";
|
||||
import { InstantReviveHeldItem, type InstantReviveParams } from "#items/instant-revive";
|
||||
@ -36,7 +35,8 @@ import { EvolutionStatBoostHeldItem, SpeciesStatBoostHeldItem, type StatBoostPar
|
||||
import { SurviveChanceHeldItem, type SurviveChanceParams } from "#items/survive-chance";
|
||||
import { TurnEndHealHeldItem, type TurnEndHealParams } from "#items/turn-end-heal";
|
||||
import { TurnEndStatusHeldItem, type TurnEndStatusParams } from "#items/turn-end-status";
|
||||
import { getEnumValues } from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
import { HeldItemEffect } from "./HeldItemEffect";
|
||||
|
||||
export function initHeldItems() {
|
||||
for (const berry of getEnumValues(BerryType)) {
|
||||
|
@ -43,7 +43,7 @@ export function initTrainerItems() {
|
||||
allTrainerItems[TrainerItemId.CANDY_JAR] = new LevelIncrementBoosterTrainerItem(TrainerItemId.CANDY_JAR, 99);
|
||||
allTrainerItems[TrainerItemId.BERRY_POUCH] = new PreserveBerryTrainerItem(TrainerItemId.BERRY_POUCH, 3);
|
||||
|
||||
allTrainerItems[TrainerItemId.HEALING_CHARM] = new HealingBoosterTrainerItem(TrainerItemId.HEALING_CHARM, 1.1, 5);
|
||||
allTrainerItems[TrainerItemId.HEALING_CHARM] = new HealingBoosterTrainerItem(TrainerItemId.HEALING_CHARM, 0.1, 5);
|
||||
allTrainerItems[TrainerItemId.EXP_CHARM] = new ExpBoosterTrainerItem(TrainerItemId.EXP_CHARM, 25, 99);
|
||||
allTrainerItems[TrainerItemId.SUPER_EXP_CHARM] = new ExpBoosterTrainerItem(TrainerItemId.SUPER_EXP_CHARM, 60, 30);
|
||||
allTrainerItems[TrainerItemId.GOLDEN_EXP_CHARM] = new ExpBoosterTrainerItem(TrainerItemId.GOLDEN_EXP_CHARM, 100, 10);
|
||||
|
@ -1,13 +1,21 @@
|
||||
// TODO: move to `src/@types/`
|
||||
// TODO: move all types to `src/@types/` and all functions to a utility place
|
||||
|
||||
import type { FormChangeItem } from "#enums/form-change-item";
|
||||
import type { HeldItemCategoryId, HeldItemId } from "#enums/held-item-id";
|
||||
import type { RewardTier } from "#enums/reward-tier";
|
||||
import type { RarityTier } from "#enums/reward-tier";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
|
||||
export type HeldItemData = {
|
||||
stack: number;
|
||||
/**
|
||||
* Whether this item is currently disabled.
|
||||
* @defaultValue `false`
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* The item's current cooldown.
|
||||
* @defaultValue `0`
|
||||
*/
|
||||
cooldown?: number;
|
||||
};
|
||||
|
||||
@ -67,7 +75,7 @@ export function isHeldItemPool(value: any): value is HeldItemPool {
|
||||
}
|
||||
|
||||
export type HeldItemTieredPool = {
|
||||
[key in RewardTier]?: HeldItemPool;
|
||||
[key in RarityTier]?: HeldItemPool;
|
||||
};
|
||||
|
||||
type HeldItemConfigurationEntry = {
|
||||
|
47
src/items/held-item-default-tiers.ts
Normal file
47
src/items/held-item-default-tiers.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { getHeldItemCategory, HeldItemCategoryId, HeldItemId } from "#enums/held-item-id";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
|
||||
export const heldItemRarities = {
|
||||
[HeldItemCategoryId.BERRY]: RarityTier.COMMON,
|
||||
|
||||
[HeldItemCategoryId.BASE_STAT_BOOST]: RarityTier.GREAT,
|
||||
[HeldItemId.WHITE_HERB]: RarityTier.GREAT,
|
||||
[HeldItemId.METAL_POWDER]: RarityTier.GREAT,
|
||||
[HeldItemId.QUICK_POWDER]: RarityTier.GREAT,
|
||||
[HeldItemId.DEEP_SEA_SCALE]: RarityTier.GREAT,
|
||||
[HeldItemId.DEEP_SEA_TOOTH]: RarityTier.GREAT,
|
||||
[HeldItemId.SOOTHE_BELL]: RarityTier.GREAT,
|
||||
|
||||
[HeldItemCategoryId.TYPE_ATTACK_BOOSTER]: RarityTier.ULTRA,
|
||||
[HeldItemId.REVIVER_SEED]: RarityTier.ULTRA,
|
||||
[HeldItemId.LIGHT_BALL]: RarityTier.ULTRA,
|
||||
[HeldItemId.EVIOLITE]: RarityTier.ULTRA,
|
||||
[HeldItemId.QUICK_CLAW]: RarityTier.ULTRA,
|
||||
[HeldItemId.MYSTICAL_ROCK]: RarityTier.ULTRA,
|
||||
[HeldItemId.WIDE_LENS]: RarityTier.ULTRA,
|
||||
[HeldItemId.GOLDEN_PUNCH]: RarityTier.ULTRA,
|
||||
[HeldItemId.TOXIC_ORB]: RarityTier.ULTRA,
|
||||
[HeldItemId.FLAME_ORB]: RarityTier.ULTRA,
|
||||
[HeldItemId.LUCKY_EGG]: RarityTier.ULTRA,
|
||||
|
||||
[HeldItemId.FOCUS_BAND]: RarityTier.ROGUE,
|
||||
[HeldItemId.KINGS_ROCK]: RarityTier.ROGUE,
|
||||
[HeldItemId.LEFTOVERS]: RarityTier.ROGUE,
|
||||
[HeldItemId.SHELL_BELL]: RarityTier.ROGUE,
|
||||
[HeldItemId.GRIP_CLAW]: RarityTier.ROGUE,
|
||||
[HeldItemId.SOUL_DEW]: RarityTier.ROGUE,
|
||||
[HeldItemId.BATON]: RarityTier.ROGUE,
|
||||
[HeldItemId.GOLDEN_EGG]: RarityTier.ULTRA,
|
||||
|
||||
[HeldItemId.MINI_BLACK_HOLE]: RarityTier.MASTER,
|
||||
[HeldItemId.MULTI_LENS]: RarityTier.MASTER,
|
||||
};
|
||||
|
||||
export function getHeldItemTier(item: HeldItemId): RarityTier {
|
||||
let tier = heldItemRarities[item];
|
||||
if (!tier) {
|
||||
const category = getHeldItemCategory(item);
|
||||
tier = heldItemRarities[category];
|
||||
}
|
||||
return tier ?? RarityTier.LUXURY;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
import { allHeldItems } from "#data/data-lists";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { HeldItemCategoryId, HeldItemId, HeldItemNames, isCategoryId } from "#enums/held-item-id";
|
||||
import { HeldItemPoolType } from "#enums/modifier-pool-type";
|
||||
import type { PokemonType } from "#enums/pokemon-type";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { HeldItemPoolType } from "#enums/reward-pool-type";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { PERMANENT_STATS } from "#enums/stat";
|
||||
import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import { attackTypeToHeldItem } from "#items/attack-type-booster";
|
||||
@ -21,7 +21,8 @@ import {
|
||||
isHeldItemPool,
|
||||
isHeldItemSpecs,
|
||||
} from "#items/held-item-data-types";
|
||||
import { coerceArray, getEnumValues, isNullOrUndefined, pickWeightedIndex, randSeedInt } from "#utils/common";
|
||||
import { coerceArray, isNullOrUndefined, pickWeightedIndex, randSeedInt } from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
|
||||
export const wildHeldItemPool: HeldItemTieredPool = {};
|
||||
|
||||
@ -34,7 +35,7 @@ export function assignDailyRunStarterHeldItems(party: PlayerPokemon[]) {
|
||||
for (let m = 0; m < 3; m++) {
|
||||
const tierValue = randSeedInt(64);
|
||||
|
||||
const tier = getDailyRewardTier(tierValue);
|
||||
const tier = getDailyRarityTier(tierValue);
|
||||
|
||||
const item = getNewHeldItemFromPool(
|
||||
getHeldItemPool(HeldItemPoolType.DAILY_STARTER)[tier] as HeldItemPool,
|
||||
@ -46,20 +47,20 @@ export function assignDailyRunStarterHeldItems(party: PlayerPokemon[]) {
|
||||
}
|
||||
}
|
||||
|
||||
function getDailyRewardTier(tierValue: number): RewardTier {
|
||||
function getDailyRarityTier(tierValue: number): RarityTier {
|
||||
if (tierValue > 25) {
|
||||
return RewardTier.COMMON;
|
||||
return RarityTier.COMMON;
|
||||
}
|
||||
if (tierValue > 12) {
|
||||
return RewardTier.GREAT;
|
||||
return RarityTier.GREAT;
|
||||
}
|
||||
if (tierValue > 4) {
|
||||
return RewardTier.ULTRA;
|
||||
return RarityTier.ULTRA;
|
||||
}
|
||||
if (tierValue > 0) {
|
||||
return RewardTier.ROGUE;
|
||||
return RarityTier.ROGUE;
|
||||
}
|
||||
return RewardTier.MASTER;
|
||||
return RarityTier.MASTER;
|
||||
}
|
||||
|
||||
function getHeldItemPool(poolType: HeldItemPoolType): HeldItemTieredPool {
|
||||
@ -101,25 +102,25 @@ export function assignEnemyHeldItemsForWave(
|
||||
}
|
||||
}
|
||||
|
||||
function getRandomTier(): RewardTier {
|
||||
function getRandomTier(): RarityTier {
|
||||
const tierValue = randSeedInt(1024);
|
||||
|
||||
if (tierValue > 255) {
|
||||
return RewardTier.COMMON;
|
||||
return RarityTier.COMMON;
|
||||
}
|
||||
if (tierValue > 60) {
|
||||
return RewardTier.GREAT;
|
||||
return RarityTier.GREAT;
|
||||
}
|
||||
if (tierValue > 12) {
|
||||
return RewardTier.ULTRA;
|
||||
return RarityTier.ULTRA;
|
||||
}
|
||||
if (tierValue) {
|
||||
return RewardTier.ROGUE;
|
||||
return RarityTier.ROGUE;
|
||||
}
|
||||
return RewardTier.MASTER;
|
||||
return RarityTier.MASTER;
|
||||
}
|
||||
|
||||
function determineItemPoolTier(pool: HeldItemTieredPool, upgradeCount?: number): RewardTier {
|
||||
function determineItemPoolTier(pool: HeldItemTieredPool, upgradeCount?: number): RarityTier {
|
||||
let tier = getRandomTier();
|
||||
|
||||
if (!upgradeCount) {
|
||||
|
@ -1,47 +0,0 @@
|
||||
import { getHeldItemCategory, HeldItemCategoryId, HeldItemId } from "#enums/held-item-id";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
|
||||
export const heldItemTiers = {
|
||||
[HeldItemCategoryId.BERRY]: RewardTier.COMMON,
|
||||
|
||||
[HeldItemCategoryId.BASE_STAT_BOOST]: RewardTier.GREAT,
|
||||
[HeldItemId.WHITE_HERB]: RewardTier.GREAT,
|
||||
[HeldItemId.METAL_POWDER]: RewardTier.GREAT,
|
||||
[HeldItemId.QUICK_POWDER]: RewardTier.GREAT,
|
||||
[HeldItemId.DEEP_SEA_SCALE]: RewardTier.GREAT,
|
||||
[HeldItemId.DEEP_SEA_TOOTH]: RewardTier.GREAT,
|
||||
[HeldItemId.SOOTHE_BELL]: RewardTier.GREAT,
|
||||
|
||||
[HeldItemCategoryId.TYPE_ATTACK_BOOSTER]: RewardTier.ULTRA,
|
||||
[HeldItemId.REVIVER_SEED]: RewardTier.ULTRA,
|
||||
[HeldItemId.LIGHT_BALL]: RewardTier.ULTRA,
|
||||
[HeldItemId.EVIOLITE]: RewardTier.ULTRA,
|
||||
[HeldItemId.QUICK_CLAW]: RewardTier.ULTRA,
|
||||
[HeldItemId.MYSTICAL_ROCK]: RewardTier.ULTRA,
|
||||
[HeldItemId.WIDE_LENS]: RewardTier.ULTRA,
|
||||
[HeldItemId.GOLDEN_PUNCH]: RewardTier.ULTRA,
|
||||
[HeldItemId.TOXIC_ORB]: RewardTier.ULTRA,
|
||||
[HeldItemId.FLAME_ORB]: RewardTier.ULTRA,
|
||||
[HeldItemId.LUCKY_EGG]: RewardTier.ULTRA,
|
||||
|
||||
[HeldItemId.FOCUS_BAND]: RewardTier.ROGUE,
|
||||
[HeldItemId.KINGS_ROCK]: RewardTier.ROGUE,
|
||||
[HeldItemId.LEFTOVERS]: RewardTier.ROGUE,
|
||||
[HeldItemId.SHELL_BELL]: RewardTier.ROGUE,
|
||||
[HeldItemId.GRIP_CLAW]: RewardTier.ROGUE,
|
||||
[HeldItemId.SOUL_DEW]: RewardTier.ROGUE,
|
||||
[HeldItemId.BATON]: RewardTier.ROGUE,
|
||||
[HeldItemId.GOLDEN_EGG]: RewardTier.ULTRA,
|
||||
|
||||
[HeldItemId.MINI_BLACK_HOLE]: RewardTier.MASTER,
|
||||
[HeldItemId.MULTI_LENS]: RewardTier.MASTER,
|
||||
};
|
||||
|
||||
export function getHeldItemTier(item: HeldItemId): RewardTier | undefined {
|
||||
let tier = heldItemTiers[item];
|
||||
if (!tier) {
|
||||
const category = getHeldItemCategory(item);
|
||||
tier = heldItemTiers[category];
|
||||
}
|
||||
return tier;
|
||||
}
|
@ -4,42 +4,9 @@ import { type HeldItemId, HeldItemNames } from "#enums/held-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import i18next from "i18next";
|
||||
|
||||
// TODO: this should be moved to its own file
|
||||
export const HeldItemEffect = {
|
||||
ATTACK_TYPE_BOOST: 1,
|
||||
TURN_END_HEAL: 2,
|
||||
HIT_HEAL: 3,
|
||||
RESET_NEGATIVE_STAT_STAGE: 4,
|
||||
EXP_BOOSTER: 5,
|
||||
// Should we actually distinguish different berry effects?
|
||||
BERRY: 6,
|
||||
BASE_STAT_BOOSTER: 7,
|
||||
INSTANT_REVIVE: 8,
|
||||
STAT_BOOST: 9,
|
||||
CRIT_BOOST: 10,
|
||||
TURN_END_STATUS: 11,
|
||||
SURVIVE_CHANCE: 12,
|
||||
BYPASS_SPEED_CHANCE: 13,
|
||||
FLINCH_CHANCE: 14,
|
||||
FIELD_EFFECT: 15,
|
||||
FRIENDSHIP_BOOSTER: 16,
|
||||
NATURE_WEIGHT_BOOSTER: 17,
|
||||
ACCURACY_BOOSTER: 18,
|
||||
MULTI_HIT: 19,
|
||||
DAMAGE_MONEY_REWARD: 20,
|
||||
BATON: 21,
|
||||
TURN_END_ITEM_STEAL: 22,
|
||||
CONTACT_ITEM_STEAL_CHANCE: 23,
|
||||
EVO_TRACKER: 40,
|
||||
BASE_STAT_TOTAL: 50,
|
||||
BASE_STAT_FLAT: 51,
|
||||
INCREMENTING_STAT: 52,
|
||||
} as const;
|
||||
|
||||
export type HeldItemEffect = (typeof HeldItemEffect)[keyof typeof HeldItemEffect];
|
||||
|
||||
export class HeldItem {
|
||||
// public pokemonId: number;
|
||||
// TODO: Should this be readonly?
|
||||
public type: HeldItemId;
|
||||
public readonly maxStackCount: number;
|
||||
public isTransferable = true;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
|
||||
export interface AccuracyBoostParams {
|
||||
@ -24,17 +25,17 @@ export class AccuracyBoosterHeldItem extends HeldItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if {@linkcode PokemonMoveAccuracyBoosterModifier} should be applied
|
||||
* Checks if {@linkcode PokemonMoveAccuracyBoosterHeldItem} should be applied
|
||||
* @param pokemon - The {@linkcode Pokemon} to apply the move accuracy boost to
|
||||
* @param moveAccuracy - {@linkcode NumberHolder} holding the move accuracy boost
|
||||
* @returns `true` if {@linkcode PokemonMoveAccuracyBoosterModifier} should be applied
|
||||
* @returns `true` if {@linkcode PokemonMoveAccuracyBoosterHeldItem} should be applied
|
||||
*/
|
||||
// override shouldApply(pokemon?: Pokemon, moveAccuracy?: NumberHolder): boolean {
|
||||
// return super.shouldApply(pokemon, moveAccuracy) && !!moveAccuracy;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Applies {@linkcode PokemonMoveAccuracyBoosterModifier}
|
||||
* Applies {@linkcode PokemonMoveAccuracyBoosterHeldItem}
|
||||
*/
|
||||
apply({ pokemon, moveAccuracy }: AccuracyBoostParams): true {
|
||||
const stackCount = pokemon.heldItemManager.getStack(this.type);
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { HeldItemId, HeldItemNames } from "#enums/held-item-id";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import { getStatKey, type PermanentStat, Stat } from "#enums/stat";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import i18next from "i18next";
|
||||
|
||||
export interface BaseStatBoosterParams {
|
||||
@ -11,9 +12,9 @@ export interface BaseStatBoosterParams {
|
||||
baseStats: number[];
|
||||
}
|
||||
|
||||
interface PermanentStatToHeldItemMap {
|
||||
[key: number]: HeldItemId;
|
||||
}
|
||||
type PermanentStatToHeldItemMap = {
|
||||
[key in PermanentStat]: HeldItemId;
|
||||
};
|
||||
|
||||
export const permanentStatToHeldItem: PermanentStatToHeldItemMap = {
|
||||
[Stat.HP]: HeldItemId.HP_UP,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { Stat } from "#enums/stat";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import i18next from "i18next";
|
||||
|
||||
export interface BaseStatFlatParams {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import i18next from "i18next";
|
||||
|
||||
export interface BaseStatTotalParams {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
|
||||
export interface BatonParams {
|
||||
|
@ -1,18 +1,21 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getBerryEffectDescription, getBerryEffectFunc, getBerryName, getBerryPredicate } from "#data/berry";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import { BerryUsedEvent } from "#events/battle-scene";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { ConsumableHeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { ConsumableHeldItem } from "#items/held-item";
|
||||
import { TrainerItemEffect } from "#items/trainer-item";
|
||||
import type { EnumValues } from "#types/enum-types";
|
||||
import { BooleanHolder } from "#utils/common";
|
||||
|
||||
interface BerryTypeToHeldItemMap {
|
||||
[key: number]: HeldItemId;
|
||||
}
|
||||
type BerryTypeToHeldItemMap = {
|
||||
[key in EnumValues<typeof BerryType>]: HeldItemId;
|
||||
};
|
||||
|
||||
export const berryTypeToHeldItem: BerryTypeToHeldItemMap = {
|
||||
// TODO: Rework this to use a bitwise XOR
|
||||
export const berryTypeToHeldItem = {
|
||||
[BerryType.SITRUS]: HeldItemId.SITRUS_BERRY,
|
||||
[BerryType.LUM]: HeldItemId.LUM_BERRY,
|
||||
[BerryType.ENIGMA]: HeldItemId.ENIGMA_BERRY,
|
||||
@ -24,7 +27,7 @@ export const berryTypeToHeldItem: BerryTypeToHeldItemMap = {
|
||||
[BerryType.LANSAT]: HeldItemId.LANSAT_BERRY,
|
||||
[BerryType.STARF]: HeldItemId.STARF_BERRY,
|
||||
[BerryType.LEPPA]: HeldItemId.LEPPA_BERRY,
|
||||
};
|
||||
} satisfies BerryTypeToHeldItemMap;
|
||||
|
||||
export interface BerryParams {
|
||||
/** The pokemon with the berry */
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { Command } from "#enums/command";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { BooleanHolder } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { SpeciesId } from "#enums/species-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
|
||||
export interface CritBoostParams {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import { TrainerItemEffect } from "#items/trainer-item";
|
||||
import { NumberHolder } from "#utils/common";
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import type { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import i18next from "i18next";
|
||||
|
||||
export interface EvoTrackerParams {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
|
||||
export interface FieldEffectParams {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { BooleanHolder } from "#utils/common";
|
||||
|
||||
export interface FlinchChanceParams {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import { PokemonHealPhase } from "#phases/pokemon-heal-phase";
|
||||
import { toDmgValue } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { Stat } from "#enums/stat";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { applyAbAttrs } from "#abilities/apply-ab-attrs";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { ConsumableHeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { ConsumableHeldItem } from "#items/held-item";
|
||||
import { PokemonHealPhase } from "#phases/pokemon-heal-phase";
|
||||
import { toDmgValue } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { allHeldItems } from "#data/data-lists";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import { coerceArray, randSeedFloat } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
@ -47,7 +48,7 @@ export abstract class ItemTransferHeldItem extends HeldItem {
|
||||
}
|
||||
|
||||
// TODO: Change this logic to use held items
|
||||
const transferredModifierTypes: HeldItemId[] = [];
|
||||
const transferredRewards: HeldItemId[] = [];
|
||||
const heldItems = targetPokemon.heldItemManager.getTransferableHeldItems();
|
||||
|
||||
for (let i = 0; i < transferredItemCount; i++) {
|
||||
@ -58,16 +59,16 @@ export abstract class ItemTransferHeldItem extends HeldItem {
|
||||
const randItem = heldItems[randItemIndex];
|
||||
// TODO: Fix this after updating the various methods in battle-scene.ts
|
||||
if (globalScene.tryTransferHeldItem(randItem, targetPokemon, pokemon, false)) {
|
||||
transferredModifierTypes.push(randItem);
|
||||
transferredRewards.push(randItem);
|
||||
heldItems.splice(randItemIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (const mt of transferredModifierTypes) {
|
||||
for (const mt of transferredRewards) {
|
||||
globalScene.phaseManager.queueMessage(this.getTransferMessage(params, mt));
|
||||
}
|
||||
|
||||
return !!transferredModifierTypes.length;
|
||||
return !!transferredRewards.length;
|
||||
}
|
||||
|
||||
abstract getTargets(params: ItemStealParams): Pokemon[];
|
||||
@ -80,7 +81,7 @@ export abstract class ItemTransferHeldItem extends HeldItem {
|
||||
/**
|
||||
* Modifier for held items that steal items from the enemy at the end of
|
||||
* each turn.
|
||||
* @see {@linkcode modifierTypes[MINI_BLACK_HOLE]}
|
||||
* @see {@linkcode allRewards[MINI_BLACK_HOLE]}
|
||||
*/
|
||||
export class TurnEndItemStealHeldItem extends ItemTransferHeldItem {
|
||||
public effects: HeldItemEffect[] = [HeldItemEffect.TURN_END_ITEM_STEAL];
|
||||
@ -121,7 +122,7 @@ export class TurnEndItemStealHeldItem extends ItemTransferHeldItem {
|
||||
/**
|
||||
* Modifier for held items that add a chance to steal items from the target of a
|
||||
* successful attack.
|
||||
* @see {@linkcode modifierTypes[GRIP_CLAW]}
|
||||
* @see {@linkcode allRewards[GRIP_CLAW]}
|
||||
* @see {@linkcode HeldItemTransferModifier}
|
||||
*/
|
||||
export class ContactItemStealChanceHeldItem extends ItemTransferHeldItem {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { allMoves } from "#data/data-lists";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import { isNullOrUndefined, type NumberHolder } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
|
||||
export interface NatureWeightBoostParams {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { BATTLE_STATS } from "#enums/stat";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { ConsumableHeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { ConsumableHeldItem } from "#items/held-item";
|
||||
import i18next from "i18next";
|
||||
|
||||
export interface ResetNegativeStatStageParams {
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { pokemonEvolutions } from "#balance/pokemon-evolutions";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import type { SpeciesId } from "#enums/species-id";
|
||||
import type { Stat } from "#enums/stat";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { NumberHolder } from "#utils/common";
|
||||
|
||||
export interface StatBoostParams {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import type { BooleanHolder } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
import { PokemonHealPhase } from "#phases/pokemon-heal-phase";
|
||||
import { toDmgValue } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { HeldItemEffect } from "#enums/held-item-effect";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import type { StatusEffect } from "#enums/status-effect";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { HeldItem, HeldItemEffect } from "#items/held-item";
|
||||
import { HeldItem } from "#items/held-item";
|
||||
|
||||
export interface TurnEndStatusParams {
|
||||
/** The pokemon with the item */
|
||||
|
@ -1,42 +1,42 @@
|
||||
import { HeldItemCategoryId, HeldItemId } from "#enums/held-item-id";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { dailyStarterHeldItemPool, trainerHeldItemPool, wildHeldItemPool } from "#items/held-item-pool";
|
||||
|
||||
/**
|
||||
* Initialize the wild held item pool
|
||||
*/
|
||||
function initWildHeldItemPool() {
|
||||
wildHeldItemPool[RewardTier.COMMON] = [{ entry: HeldItemCategoryId.BERRY, weight: 1 }];
|
||||
wildHeldItemPool[RewardTier.GREAT] = [{ entry: HeldItemCategoryId.BASE_STAT_BOOST, weight: 1 }];
|
||||
wildHeldItemPool[RewardTier.ULTRA] = [
|
||||
wildHeldItemPool[RarityTier.COMMON] = [{ entry: HeldItemCategoryId.BERRY, weight: 1 }];
|
||||
wildHeldItemPool[RarityTier.GREAT] = [{ entry: HeldItemCategoryId.BASE_STAT_BOOST, weight: 1 }];
|
||||
wildHeldItemPool[RarityTier.ULTRA] = [
|
||||
{ entry: HeldItemCategoryId.TYPE_ATTACK_BOOSTER, weight: 5 },
|
||||
{ entry: HeldItemId.WHITE_HERB, weight: 0 },
|
||||
];
|
||||
wildHeldItemPool[RewardTier.ROGUE] = [{ entry: HeldItemId.LUCKY_EGG, weight: 4 }];
|
||||
wildHeldItemPool[RewardTier.MASTER] = [{ entry: HeldItemId.GOLDEN_EGG, weight: 1 }];
|
||||
wildHeldItemPool[RarityTier.ROGUE] = [{ entry: HeldItemId.LUCKY_EGG, weight: 4 }];
|
||||
wildHeldItemPool[RarityTier.MASTER] = [{ entry: HeldItemId.GOLDEN_EGG, weight: 1 }];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the trainer pokemon held item pool
|
||||
*/
|
||||
function initTrainerHeldItemPool() {
|
||||
trainerHeldItemPool[RewardTier.COMMON] = [
|
||||
trainerHeldItemPool[RarityTier.COMMON] = [
|
||||
{ entry: HeldItemCategoryId.BERRY, weight: 8 },
|
||||
{ entry: HeldItemCategoryId.BASE_STAT_BOOST, weight: 3 },
|
||||
];
|
||||
trainerHeldItemPool[RewardTier.GREAT] = [{ entry: HeldItemCategoryId.BASE_STAT_BOOST, weight: 3 }];
|
||||
trainerHeldItemPool[RewardTier.ULTRA] = [
|
||||
trainerHeldItemPool[RarityTier.GREAT] = [{ entry: HeldItemCategoryId.BASE_STAT_BOOST, weight: 3 }];
|
||||
trainerHeldItemPool[RarityTier.ULTRA] = [
|
||||
{ entry: HeldItemCategoryId.TYPE_ATTACK_BOOSTER, weight: 10 },
|
||||
{ entry: HeldItemId.WHITE_HERB, weight: 0 },
|
||||
];
|
||||
trainerHeldItemPool[RewardTier.ROGUE] = [
|
||||
trainerHeldItemPool[RarityTier.ROGUE] = [
|
||||
{ entry: HeldItemId.FOCUS_BAND, weight: 2 },
|
||||
{ entry: HeldItemId.LUCKY_EGG, weight: 4 },
|
||||
{ entry: HeldItemId.QUICK_CLAW, weight: 1 },
|
||||
{ entry: HeldItemId.GRIP_CLAW, weight: 1 },
|
||||
{ entry: HeldItemId.WIDE_LENS, weight: 1 },
|
||||
];
|
||||
trainerHeldItemPool[RewardTier.MASTER] = [
|
||||
trainerHeldItemPool[RarityTier.MASTER] = [
|
||||
{ entry: HeldItemId.KINGS_ROCK, weight: 1 },
|
||||
{ entry: HeldItemId.LEFTOVERS, weight: 1 },
|
||||
{ entry: HeldItemId.SHELL_BELL, weight: 1 },
|
||||
@ -47,26 +47,26 @@ function initTrainerHeldItemPool() {
|
||||
/**
|
||||
* Initialize the daily starter held item pool
|
||||
*/
|
||||
function initDailyStarterModifierPool() {
|
||||
dailyStarterHeldItemPool[RewardTier.COMMON] = [
|
||||
function initDailyStarterRewardPool() {
|
||||
dailyStarterHeldItemPool[RarityTier.COMMON] = [
|
||||
{ entry: HeldItemCategoryId.BASE_STAT_BOOST, weight: 1 },
|
||||
{ entry: HeldItemCategoryId.BERRY, weight: 3 },
|
||||
];
|
||||
dailyStarterHeldItemPool[RewardTier.GREAT] = [{ entry: HeldItemCategoryId.TYPE_ATTACK_BOOSTER, weight: 5 }];
|
||||
dailyStarterHeldItemPool[RewardTier.ULTRA] = [
|
||||
dailyStarterHeldItemPool[RarityTier.GREAT] = [{ entry: HeldItemCategoryId.TYPE_ATTACK_BOOSTER, weight: 5 }];
|
||||
dailyStarterHeldItemPool[RarityTier.ULTRA] = [
|
||||
{ entry: HeldItemId.REVIVER_SEED, weight: 4 },
|
||||
{ entry: HeldItemId.SOOTHE_BELL, weight: 1 },
|
||||
{ entry: HeldItemId.SOUL_DEW, weight: 1 },
|
||||
{ entry: HeldItemId.GOLDEN_PUNCH, weight: 1 },
|
||||
];
|
||||
dailyStarterHeldItemPool[RewardTier.ROGUE] = [
|
||||
dailyStarterHeldItemPool[RarityTier.ROGUE] = [
|
||||
{ entry: HeldItemId.GRIP_CLAW, weight: 5 },
|
||||
{ entry: HeldItemId.BATON, weight: 2 },
|
||||
{ entry: HeldItemId.FOCUS_BAND, weight: 5 },
|
||||
{ entry: HeldItemId.QUICK_CLAW, weight: 3 },
|
||||
{ entry: HeldItemId.KINGS_ROCK, weight: 3 },
|
||||
];
|
||||
dailyStarterHeldItemPool[RewardTier.MASTER] = [
|
||||
dailyStarterHeldItemPool[RarityTier.MASTER] = [
|
||||
{ entry: HeldItemId.LEFTOVERS, weight: 1 },
|
||||
{ entry: HeldItemId.SHELL_BELL, weight: 1 },
|
||||
];
|
||||
@ -76,5 +76,5 @@ export function initHeldItemPools() {
|
||||
// Default held item pools for specific scenarios
|
||||
initWildHeldItemPool();
|
||||
initTrainerHeldItemPool();
|
||||
initDailyStarterModifierPool();
|
||||
initDailyStarterRewardPool();
|
||||
}
|
||||
|
@ -1,37 +1,37 @@
|
||||
/* biome-ignore-start lint/correctness/noUnusedImports: tsdoc imports */
|
||||
import type { initModifierTypes } from "#modifiers/modifier-type";
|
||||
import type { initRewards, Reward } from "#items/reward";
|
||||
/* biome-ignore-end lint/correctness/noUnusedImports: tsdoc imports */
|
||||
|
||||
import { timedEventManager } from "#app/global-event-manager";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { pokemonEvolutions } from "#balance/pokemon-evolutions";
|
||||
import { allHeldItems, allTrainerItems, modifierTypes } from "#data/data-lists";
|
||||
import { allHeldItems, allRewards, allTrainerItems } from "#data/data-lists";
|
||||
import { MAX_PER_TYPE_POKEBALLS } from "#data/pokeball";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { HeldItemId } from "#enums/held-item-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import { Unlockables } from "#enums/unlockables";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { WeightedReward } from "#items/reward";
|
||||
import { rewardPool } from "#items/reward-pools";
|
||||
import type { TurnEndStatusHeldItem } from "#items/turn-end-status";
|
||||
import { modifierPool } from "#modifiers/modifier-pools";
|
||||
import { WeightedModifierType } from "#modifiers/modifier-type";
|
||||
import type { WeightedModifierTypeWeightFunc } from "#types/modifier-types";
|
||||
import type { WeightedRewardWeightFunc } from "#types/rewards";
|
||||
import { isNullOrUndefined } from "#utils/common";
|
||||
|
||||
/**
|
||||
* Initialize the common modifier pool
|
||||
*/
|
||||
function initCommonModifierPool() {
|
||||
modifierPool[RewardTier.COMMON] = [
|
||||
new WeightedModifierType(modifierTypes.POKEBALL, () => (hasMaximumBalls(PokeballType.POKEBALL) ? 0 : 6), 6),
|
||||
new WeightedModifierType(modifierTypes.RARE_CANDY, 2),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.POTION,
|
||||
function initCommonRewardPool() {
|
||||
rewardPool[RarityTier.COMMON] = [
|
||||
new WeightedReward(allRewards.POKEBALL, () => (hasMaximumBalls(PokeballType.POKEBALL) ? 0 : 6), 6),
|
||||
new WeightedReward(allRewards.RARE_CANDY, 2),
|
||||
new WeightedReward(
|
||||
allRewards.POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 10 && p.getHpRatio() <= 0.875 && !p.isFainted()).length,
|
||||
@ -41,8 +41,8 @@ function initCommonModifierPool() {
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.SUPER_POTION,
|
||||
new WeightedReward(
|
||||
allRewards.SUPER_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 25 && p.getHpRatio() <= 0.75 && !p.isFainted()).length,
|
||||
@ -52,8 +52,8 @@ function initCommonModifierPool() {
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.ETHER,
|
||||
new WeightedReward(
|
||||
allRewards.ETHER,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
@ -71,8 +71,8 @@ function initCommonModifierPool() {
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_ETHER,
|
||||
new WeightedReward(
|
||||
allRewards.MAX_ETHER,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
@ -90,25 +90,22 @@ function initCommonModifierPool() {
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.LURE, lureWeightFunc(TrainerItemId.LURE, 2)),
|
||||
new WeightedModifierType(modifierTypes.TEMP_STAT_STAGE_BOOSTER, 4),
|
||||
new WeightedModifierType(modifierTypes.BERRY, 2),
|
||||
new WeightedModifierType(modifierTypes.TM_COMMON, 2),
|
||||
].map(m => {
|
||||
m.setTier(RewardTier.COMMON);
|
||||
return m;
|
||||
});
|
||||
new WeightedReward(allRewards.LURE, lureWeightFunc(TrainerItemId.LURE, 2)),
|
||||
new WeightedReward(allRewards.TEMP_STAT_STAGE_BOOSTER, 4),
|
||||
new WeightedReward(allRewards.BERRY, 2),
|
||||
new WeightedReward(allRewards.TM_COMMON, 2),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Great modifier pool
|
||||
*/
|
||||
function initGreatModifierPool() {
|
||||
modifierPool[RewardTier.GREAT] = [
|
||||
new WeightedModifierType(modifierTypes.GREAT_BALL, () => (hasMaximumBalls(PokeballType.GREAT_BALL) ? 0 : 6), 6),
|
||||
new WeightedModifierType(modifierTypes.PP_UP, 2),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FULL_HEAL,
|
||||
function initGreatRewardPool() {
|
||||
rewardPool[RarityTier.GREAT] = [
|
||||
new WeightedReward(allRewards.GREAT_BALL, () => (hasMaximumBalls(PokeballType.GREAT_BALL) ? 0 : 6), 6),
|
||||
new WeightedReward(allRewards.PP_UP, 2),
|
||||
new WeightedReward(
|
||||
allRewards.FULL_HEAL,
|
||||
(party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
@ -126,31 +123,31 @@ function initGreatModifierPool() {
|
||||
},
|
||||
18,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.REVIVE,
|
||||
new WeightedReward(
|
||||
allRewards.REVIVE,
|
||||
(party: Pokemon[]) => {
|
||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||
return faintedPartyMemberCount * 9;
|
||||
},
|
||||
27,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_REVIVE,
|
||||
new WeightedReward(
|
||||
allRewards.MAX_REVIVE,
|
||||
(party: Pokemon[]) => {
|
||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||
return faintedPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.SACRED_ASH,
|
||||
new WeightedReward(
|
||||
allRewards.SACRED_ASH,
|
||||
(party: Pokemon[]) => {
|
||||
return party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
||||
},
|
||||
1,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.HYPER_POTION,
|
||||
new WeightedReward(
|
||||
allRewards.HYPER_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.625 && !p.isFainted()).length,
|
||||
@ -160,8 +157,8 @@ function initGreatModifierPool() {
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_POTION,
|
||||
new WeightedReward(
|
||||
allRewards.MAX_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.5 && !p.isFainted()).length,
|
||||
@ -171,8 +168,8 @@ function initGreatModifierPool() {
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FULL_RESTORE,
|
||||
new WeightedReward(
|
||||
allRewards.FULL_RESTORE,
|
||||
(party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
@ -195,8 +192,8 @@ function initGreatModifierPool() {
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.ELIXIR,
|
||||
new WeightedReward(
|
||||
allRewards.ELIXIR,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
@ -214,8 +211,8 @@ function initGreatModifierPool() {
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_ELIXIR,
|
||||
new WeightedReward(
|
||||
allRewards.MAX_ELIXIR,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
@ -233,26 +230,26 @@ function initGreatModifierPool() {
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.DIRE_HIT, 4),
|
||||
new WeightedModifierType(modifierTypes.SUPER_LURE, lureWeightFunc(TrainerItemId.SUPER_LURE, 4)),
|
||||
new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)),
|
||||
new WeightedModifierType(modifierTypes.SPECIES_STAT_BOOSTER, 4),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.EVOLUTION_ITEM,
|
||||
new WeightedReward(allRewards.DIRE_HIT, 4),
|
||||
new WeightedReward(allRewards.SUPER_LURE, lureWeightFunc(TrainerItemId.SUPER_LURE, 4)),
|
||||
new WeightedReward(allRewards.NUGGET, skipInLastClassicWaveOrDefault(5)),
|
||||
new WeightedReward(allRewards.SPECIES_STAT_BOOSTER, 4),
|
||||
new WeightedReward(
|
||||
allRewards.EVOLUTION_ITEM,
|
||||
() => {
|
||||
return Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 15), 8);
|
||||
},
|
||||
8,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAP,
|
||||
new WeightedReward(
|
||||
allRewards.MAP,
|
||||
() => (globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex < 180 ? 2 : 0),
|
||||
2,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.SOOTHE_BELL, 2),
|
||||
new WeightedModifierType(modifierTypes.TM_GREAT, 3),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MEMORY_MUSHROOM,
|
||||
new WeightedReward(allRewards.SOOTHE_BELL, 2),
|
||||
new WeightedReward(allRewards.TM_GREAT, 3),
|
||||
new WeightedReward(
|
||||
allRewards.MEMORY_MUSHROOM,
|
||||
(party: Pokemon[]) => {
|
||||
if (!party.find(p => p.getLearnableLevelMoves().length)) {
|
||||
return 0;
|
||||
@ -264,8 +261,8 @@ function initGreatModifierPool() {
|
||||
},
|
||||
4,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3),
|
||||
new WeightedModifierType(modifierTypes.TERA_SHARD, (party: Pokemon[]) =>
|
||||
new WeightedReward(allRewards.BASE_STAT_BOOSTER, 3),
|
||||
new WeightedReward(allRewards.TERA_SHARD, (party: Pokemon[]) =>
|
||||
party.filter(
|
||||
p =>
|
||||
!(p.hasSpecies(SpeciesId.TERAPAGOS) || p.hasSpecies(SpeciesId.OGERPON) || p.hasSpecies(SpeciesId.SHEDINJA)),
|
||||
@ -273,8 +270,8 @@ function initGreatModifierPool() {
|
||||
? 1
|
||||
: 0,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.DNA_SPLICERS,
|
||||
new WeightedReward(
|
||||
allRewards.DNA_SPLICERS,
|
||||
(party: Pokemon[]) => {
|
||||
if (party.filter(p => !p.fusionSpecies).length > 1) {
|
||||
if (globalScene.gameMode.isSplicedOnly) {
|
||||
@ -288,39 +285,36 @@ function initGreatModifierPool() {
|
||||
},
|
||||
4,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.VOUCHER,
|
||||
new WeightedReward(
|
||||
allRewards.VOUCHER,
|
||||
(_party: Pokemon[], rerollCount: number) => (!globalScene.gameMode.isDaily ? Math.max(1 - rerollCount, 0) : 0),
|
||||
1,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(RewardTier.GREAT);
|
||||
return m;
|
||||
});
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Ultra modifier pool
|
||||
*/
|
||||
function initUltraModifierPool() {
|
||||
modifierPool[RewardTier.ULTRA] = [
|
||||
new WeightedModifierType(modifierTypes.ULTRA_BALL, () => (hasMaximumBalls(PokeballType.ULTRA_BALL) ? 0 : 15), 15),
|
||||
new WeightedModifierType(modifierTypes.MAX_LURE, lureWeightFunc(TrainerItemId.MAX_LURE, 4)),
|
||||
new WeightedModifierType(modifierTypes.BIG_NUGGET, skipInLastClassicWaveOrDefault(12)),
|
||||
new WeightedModifierType(modifierTypes.PP_MAX, 3),
|
||||
new WeightedModifierType(modifierTypes.MINT, 4),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.RARE_EVOLUTION_ITEM,
|
||||
function initUltraRewardPool() {
|
||||
rewardPool[RarityTier.ULTRA] = [
|
||||
new WeightedReward(allRewards.ULTRA_BALL, () => (hasMaximumBalls(PokeballType.ULTRA_BALL) ? 0 : 15), 15),
|
||||
new WeightedReward(allRewards.MAX_LURE, lureWeightFunc(TrainerItemId.MAX_LURE, 4)),
|
||||
new WeightedReward(allRewards.BIG_NUGGET, skipInLastClassicWaveOrDefault(12)),
|
||||
new WeightedReward(allRewards.PP_MAX, 3),
|
||||
new WeightedReward(allRewards.MINT, 4),
|
||||
new WeightedReward(
|
||||
allRewards.RARE_EVOLUTION_ITEM,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 15) * 4, 32),
|
||||
32,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FORM_CHANGE_ITEM,
|
||||
new WeightedReward(
|
||||
allRewards.FORM_CHANGE_ITEM,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 6,
|
||||
24,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.AMULET_COIN, skipInLastClassicWaveOrDefault(3)),
|
||||
new WeightedModifierType(modifierTypes.EVIOLITE, (party: Pokemon[]) => {
|
||||
new WeightedReward(allRewards.AMULET_COIN, skipInLastClassicWaveOrDefault(3)),
|
||||
new WeightedReward(allRewards.EVIOLITE, (party: Pokemon[]) => {
|
||||
const { gameMode, gameData } = globalScene;
|
||||
if (gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) {
|
||||
return party.some(p => {
|
||||
@ -340,9 +334,9 @@ function initUltraModifierPool() {
|
||||
}
|
||||
return 0;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.RARE_SPECIES_STAT_BOOSTER, 12),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.LEEK,
|
||||
new WeightedReward(allRewards.RARE_SPECIES_STAT_BOOSTER, 12),
|
||||
new WeightedReward(
|
||||
allRewards.LEEK,
|
||||
(party: Pokemon[]) => {
|
||||
const checkedSpecies = [SpeciesId.FARFETCHD, SpeciesId.GALAR_FARFETCHD, SpeciesId.SIRFETCHD];
|
||||
// If a party member doesn't already have a Leek and is one of the relevant species, Leek can appear
|
||||
@ -357,8 +351,8 @@ function initUltraModifierPool() {
|
||||
},
|
||||
12,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.TOXIC_ORB,
|
||||
new WeightedReward(
|
||||
allRewards.TOXIC_ORB,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
const isHoldingOrb = p.getHeldItems().some(i => i in [HeldItemId.FLAME_ORB, HeldItemId.TOXIC_ORB]);
|
||||
@ -403,8 +397,8 @@ function initUltraModifierPool() {
|
||||
},
|
||||
10,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FLAME_ORB,
|
||||
new WeightedReward(
|
||||
allRewards.FLAME_ORB,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
const isHoldingOrb = p.getHeldItems().some(i => i in [HeldItemId.FLAME_ORB, HeldItemId.TOXIC_ORB]);
|
||||
@ -449,8 +443,8 @@ function initUltraModifierPool() {
|
||||
},
|
||||
10,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MYSTICAL_ROCK,
|
||||
new WeightedReward(
|
||||
allRewards.MYSTICAL_ROCK,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
const stack = p.heldItemManager.getStack(HeldItemId.MYSTICAL_ROCK);
|
||||
@ -496,94 +490,88 @@ function initUltraModifierPool() {
|
||||
},
|
||||
10,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.REVIVER_SEED, 4),
|
||||
new WeightedModifierType(modifierTypes.CANDY_JAR, skipInLastClassicWaveOrDefault(5)),
|
||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 9),
|
||||
new WeightedModifierType(modifierTypes.TM_ULTRA, 11),
|
||||
new WeightedModifierType(modifierTypes.RARER_CANDY, 4),
|
||||
new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, skipInLastClassicWaveOrDefault(2)),
|
||||
new WeightedModifierType(modifierTypes.IV_SCANNER, skipInLastClassicWaveOrDefault(4)),
|
||||
new WeightedModifierType(modifierTypes.EXP_CHARM, skipInLastClassicWaveOrDefault(8)),
|
||||
new WeightedModifierType(modifierTypes.EXP_SHARE, skipInLastClassicWaveOrDefault(10)),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.TERA_ORB,
|
||||
new WeightedReward(allRewards.REVIVER_SEED, 4),
|
||||
new WeightedReward(allRewards.CANDY_JAR, skipInLastClassicWaveOrDefault(5)),
|
||||
new WeightedReward(allRewards.ATTACK_TYPE_BOOSTER, 9),
|
||||
new WeightedReward(allRewards.TM_ULTRA, 11),
|
||||
new WeightedReward(allRewards.RARER_CANDY, 4),
|
||||
new WeightedReward(allRewards.GOLDEN_PUNCH, skipInLastClassicWaveOrDefault(2)),
|
||||
new WeightedReward(allRewards.IV_SCANNER, skipInLastClassicWaveOrDefault(4)),
|
||||
new WeightedReward(allRewards.EXP_CHARM, skipInLastClassicWaveOrDefault(8)),
|
||||
new WeightedReward(allRewards.EXP_SHARE, skipInLastClassicWaveOrDefault(10)),
|
||||
new WeightedReward(
|
||||
allRewards.TERA_ORB,
|
||||
() =>
|
||||
!globalScene.gameMode.isClassic
|
||||
? Math.min(Math.max(Math.floor(globalScene.currentBattle.waveIndex / 50) * 2, 1), 4)
|
||||
: 0,
|
||||
4,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.QUICK_CLAW, 3),
|
||||
new WeightedModifierType(modifierTypes.WIDE_LENS, 7),
|
||||
].map(m => {
|
||||
m.setTier(RewardTier.ULTRA);
|
||||
return m;
|
||||
});
|
||||
new WeightedReward(allRewards.QUICK_CLAW, 3),
|
||||
new WeightedReward(allRewards.WIDE_LENS, 7),
|
||||
];
|
||||
}
|
||||
|
||||
function initRogueModifierPool() {
|
||||
modifierPool[RewardTier.ROGUE] = [
|
||||
new WeightedModifierType(modifierTypes.ROGUE_BALL, () => (hasMaximumBalls(PokeballType.ROGUE_BALL) ? 0 : 16), 16),
|
||||
new WeightedModifierType(modifierTypes.RELIC_GOLD, skipInLastClassicWaveOrDefault(2)),
|
||||
new WeightedModifierType(modifierTypes.LEFTOVERS, 3),
|
||||
new WeightedModifierType(modifierTypes.SHELL_BELL, 3),
|
||||
new WeightedModifierType(modifierTypes.BERRY_POUCH, 4),
|
||||
new WeightedModifierType(modifierTypes.GRIP_CLAW, 5),
|
||||
new WeightedModifierType(modifierTypes.SCOPE_LENS, 4),
|
||||
new WeightedModifierType(modifierTypes.BATON, 2),
|
||||
new WeightedModifierType(modifierTypes.SOUL_DEW, 7),
|
||||
new WeightedModifierType(modifierTypes.CATCHING_CHARM, () => (!globalScene.gameMode.isClassic ? 4 : 0), 4),
|
||||
new WeightedModifierType(modifierTypes.ABILITY_CHARM, skipInClassicAfterWave(189, 6)),
|
||||
new WeightedModifierType(modifierTypes.FOCUS_BAND, 5),
|
||||
new WeightedModifierType(modifierTypes.KINGS_ROCK, 3),
|
||||
new WeightedModifierType(modifierTypes.LOCK_CAPSULE, () => (globalScene.gameMode.isClassic ? 0 : 3)),
|
||||
new WeightedModifierType(modifierTypes.SUPER_EXP_CHARM, skipInLastClassicWaveOrDefault(8)),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.RARE_FORM_CHANGE_ITEM,
|
||||
function initRogueRewardPool() {
|
||||
rewardPool[RarityTier.ROGUE] = [
|
||||
new WeightedReward(allRewards.ROGUE_BALL, () => (hasMaximumBalls(PokeballType.ROGUE_BALL) ? 0 : 16), 16),
|
||||
new WeightedReward(allRewards.RELIC_GOLD, skipInLastClassicWaveOrDefault(2)),
|
||||
new WeightedReward(allRewards.LEFTOVERS, 3),
|
||||
new WeightedReward(allRewards.SHELL_BELL, 3),
|
||||
new WeightedReward(allRewards.BERRY_POUCH, 4),
|
||||
new WeightedReward(allRewards.GRIP_CLAW, 5),
|
||||
new WeightedReward(allRewards.SCOPE_LENS, 4),
|
||||
new WeightedReward(allRewards.BATON, 2),
|
||||
new WeightedReward(allRewards.SOUL_DEW, 7),
|
||||
new WeightedReward(allRewards.CATCHING_CHARM, () => (!globalScene.gameMode.isClassic ? 4 : 0), 4),
|
||||
new WeightedReward(allRewards.ABILITY_CHARM, skipInClassicAfterWave(189, 6)),
|
||||
new WeightedReward(allRewards.FOCUS_BAND, 5),
|
||||
new WeightedReward(allRewards.KINGS_ROCK, 3),
|
||||
new WeightedReward(allRewards.LOCK_CAPSULE, () => (globalScene.gameMode.isClassic ? 0 : 3)),
|
||||
new WeightedReward(allRewards.SUPER_EXP_CHARM, skipInLastClassicWaveOrDefault(8)),
|
||||
new WeightedReward(
|
||||
allRewards.RARE_FORM_CHANGE_ITEM,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 6,
|
||||
24,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MEGA_BRACELET,
|
||||
new WeightedReward(
|
||||
allRewards.MEGA_BRACELET,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9,
|
||||
36,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.DYNAMAX_BAND,
|
||||
new WeightedReward(
|
||||
allRewards.DYNAMAX_BAND,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9,
|
||||
36,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.VOUCHER_PLUS,
|
||||
new WeightedReward(
|
||||
allRewards.VOUCHER_PLUS,
|
||||
(_party: Pokemon[], rerollCount: number) =>
|
||||
!globalScene.gameMode.isDaily ? Math.max(3 - rerollCount * 1, 0) : 0,
|
||||
3,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(RewardTier.ROGUE);
|
||||
return m;
|
||||
});
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Master modifier pool
|
||||
*/
|
||||
function initMasterModifierPool() {
|
||||
modifierPool[RewardTier.MASTER] = [
|
||||
new WeightedModifierType(modifierTypes.MASTER_BALL, () => (hasMaximumBalls(PokeballType.MASTER_BALL) ? 0 : 24), 24),
|
||||
new WeightedModifierType(modifierTypes.SHINY_CHARM, 14),
|
||||
new WeightedModifierType(modifierTypes.HEALING_CHARM, 18),
|
||||
new WeightedModifierType(modifierTypes.MULTI_LENS, 18),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.VOUCHER_PREMIUM,
|
||||
function initMasterRewardPool() {
|
||||
rewardPool[RarityTier.MASTER] = [
|
||||
new WeightedReward(allRewards.MASTER_BALL, () => (hasMaximumBalls(PokeballType.MASTER_BALL) ? 0 : 24), 24),
|
||||
new WeightedReward(allRewards.SHINY_CHARM, 14),
|
||||
new WeightedReward(allRewards.HEALING_CHARM, 18),
|
||||
new WeightedReward(allRewards.MULTI_LENS, 18),
|
||||
new WeightedReward(
|
||||
allRewards.VOUCHER_PREMIUM,
|
||||
(_party: Pokemon[], rerollCount: number) =>
|
||||
!globalScene.gameMode.isDaily && !globalScene.gameMode.isEndless && !globalScene.gameMode.isSplicedOnly
|
||||
? Math.max(5 - rerollCount * 2, 0)
|
||||
: 0,
|
||||
5,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.DNA_SPLICERS,
|
||||
new WeightedReward(
|
||||
allRewards.DNA_SPLICERS,
|
||||
(party: Pokemon[]) =>
|
||||
!(globalScene.gameMode.isClassic && timedEventManager.areFusionsBoosted()) &&
|
||||
!globalScene.gameMode.isSplicedOnly &&
|
||||
@ -592,8 +580,8 @@ function initMasterModifierPool() {
|
||||
: 0,
|
||||
24,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MINI_BLACK_HOLE,
|
||||
new WeightedReward(
|
||||
allRewards.MINI_BLACK_HOLE,
|
||||
() =>
|
||||
globalScene.gameMode.isDaily ||
|
||||
(!globalScene.gameMode.isFreshStartChallenge() && globalScene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE))
|
||||
@ -601,33 +589,30 @@ function initMasterModifierPool() {
|
||||
: 0,
|
||||
1,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(RewardTier.MASTER);
|
||||
return m;
|
||||
});
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize {@linkcode modifierPool} with the initial set of modifier types.
|
||||
* {@linkcode initModifierTypes} MUST be called before this function.
|
||||
* Initialize {@linkcode rewardPool} with the initial set of modifier types.
|
||||
* {@linkcode initRewards} MUST be called before this function.
|
||||
*/
|
||||
export function initModifierPools() {
|
||||
export function initRewardPools() {
|
||||
// The modifier pools the player chooses from during modifier selection
|
||||
initCommonModifierPool();
|
||||
initGreatModifierPool();
|
||||
initUltraModifierPool();
|
||||
initRogueModifierPool();
|
||||
initMasterModifierPool();
|
||||
initCommonRewardPool();
|
||||
initGreatRewardPool();
|
||||
initUltraRewardPool();
|
||||
initRogueRewardPool();
|
||||
initMasterRewardPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* High order function that returns a WeightedModifierTypeWeightFunc that will only be applied on
|
||||
* classic and skip an ModifierType if current wave is greater or equal to the one passed down
|
||||
* High order function that returns a WeightedRewardWeightFunc that will only be applied on
|
||||
* classic and skip an Reward if current wave is greater or equal to the one passed down
|
||||
* @param wave - Wave where we should stop showing the modifier
|
||||
* @param defaultWeight - ModifierType default weight
|
||||
* @returns A WeightedModifierTypeWeightFunc
|
||||
* @param defaultWeight - Reward default weight
|
||||
* @returns A WeightedRewardWeightFunc
|
||||
*/
|
||||
function skipInClassicAfterWave(wave: number, defaultWeight: number): WeightedModifierTypeWeightFunc {
|
||||
function skipInClassicAfterWave(wave: number, defaultWeight: number): WeightedRewardWeightFunc {
|
||||
return () => {
|
||||
const gameMode = globalScene.gameMode;
|
||||
const currentWave = globalScene.currentBattle.waveIndex;
|
||||
@ -636,23 +621,23 @@ function skipInClassicAfterWave(wave: number, defaultWeight: number): WeightedMo
|
||||
}
|
||||
|
||||
/**
|
||||
* High order function that returns a WeightedModifierTypeWeightFunc that will only be applied on
|
||||
* classic and it will skip a ModifierType if it is the last wave pull.
|
||||
* @param defaultWeight ModifierType default weight
|
||||
* @returns A WeightedModifierTypeWeightFunc
|
||||
* High order function that returns a WeightedRewardWeightFunc that will only be applied on
|
||||
* classic and it will skip a Reward if it is the last wave pull.
|
||||
* @param defaultWeight Reward default weight
|
||||
* @returns A WeightedRewardWeightFunc
|
||||
*/
|
||||
function skipInLastClassicWaveOrDefault(defaultWeight: number): WeightedModifierTypeWeightFunc {
|
||||
function skipInLastClassicWaveOrDefault(defaultWeight: number): WeightedRewardWeightFunc {
|
||||
return skipInClassicAfterWave(199, defaultWeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* High order function that returns a WeightedModifierTypeWeightFunc to ensure Lures don't spawn on Classic 199
|
||||
* High order function that returns a WeightedRewardWeightFunc to ensure Lures don't spawn on Classic 199
|
||||
* or if the lure still has over 60% of its duration left
|
||||
* @param lureId The id of the lure type in question.
|
||||
* @param weight The desired weight for the lure when it does spawn
|
||||
* @returns A WeightedModifierTypeWeightFunc
|
||||
* @returns A WeightedRewardWeightFunc
|
||||
*/
|
||||
function lureWeightFunc(lureId: TrainerItemId, weight: number): WeightedModifierTypeWeightFunc {
|
||||
function lureWeightFunc(lureId: TrainerItemId, weight: number): WeightedRewardWeightFunc {
|
||||
return () => {
|
||||
const lureCount = globalScene.trainerItems.getStack(lureId);
|
||||
return !(globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex === 199) &&
|
@ -1,4 +1,4 @@
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import { enemyBuffTokenPool } from "#items/trainer-item-pool";
|
||||
|
||||
@ -6,7 +6,7 @@ import { enemyBuffTokenPool } from "#items/trainer-item-pool";
|
||||
* Initialize the enemy buff modifier pool
|
||||
*/
|
||||
function initEnemyBuffTokenPool() {
|
||||
enemyBuffTokenPool[RewardTier.COMMON] = [
|
||||
enemyBuffTokenPool[RarityTier.COMMON] = [
|
||||
{ entry: TrainerItemId.ENEMY_DAMAGE_BOOSTER, weight: 9 },
|
||||
{ entry: TrainerItemId.ENEMY_DAMAGE_REDUCTION, weight: 9 },
|
||||
{ entry: TrainerItemId.ENEMY_ATTACK_POISON_CHANCE, weight: 3 },
|
||||
@ -16,14 +16,14 @@ function initEnemyBuffTokenPool() {
|
||||
{ entry: TrainerItemId.ENEMY_ENDURE_CHANCE, weight: 4 },
|
||||
{ entry: TrainerItemId.ENEMY_FUSED_CHANCE, weight: 1 },
|
||||
];
|
||||
enemyBuffTokenPool[RewardTier.GREAT] = [
|
||||
enemyBuffTokenPool[RarityTier.GREAT] = [
|
||||
{ entry: TrainerItemId.ENEMY_DAMAGE_BOOSTER, weight: 5 },
|
||||
{ entry: TrainerItemId.ENEMY_DAMAGE_REDUCTION, weight: 5 },
|
||||
{ entry: TrainerItemId.ENEMY_STATUS_EFFECT_HEAL_CHANCE, weight: 5 },
|
||||
{ entry: TrainerItemId.ENEMY_ENDURE_CHANCE, weight: 5 },
|
||||
{ entry: TrainerItemId.ENEMY_FUSED_CHANCE, weight: 1 },
|
||||
];
|
||||
enemyBuffTokenPool[RewardTier.ULTRA] = [
|
||||
enemyBuffTokenPool[RarityTier.ULTRA] = [
|
||||
{ entry: TrainerItemId.ENEMY_DAMAGE_BOOSTER, weight: 10 },
|
||||
{ entry: TrainerItemId.ENEMY_DAMAGE_REDUCTION, weight: 10 },
|
||||
{ entry: TrainerItemId.ENEMY_HEAL, weight: 10 },
|
||||
@ -31,8 +31,8 @@ function initEnemyBuffTokenPool() {
|
||||
{ entry: TrainerItemId.ENEMY_ENDURE_CHANCE, weight: 10 },
|
||||
{ entry: TrainerItemId.ENEMY_FUSED_CHANCE, weight: 5 },
|
||||
];
|
||||
enemyBuffTokenPool[RewardTier.ROGUE] = [];
|
||||
enemyBuffTokenPool[RewardTier.MASTER] = [];
|
||||
enemyBuffTokenPool[RarityTier.ROGUE] = [];
|
||||
enemyBuffTokenPool[RarityTier.MASTER] = [];
|
||||
}
|
||||
|
||||
export function initTrainerItemPools() {
|
||||
|
50
src/items/item-overrides.ts
Normal file
50
src/items/item-overrides.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import Overrides from "#app/overrides";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { HeldItemConfiguration } from "#items/held-item-data-types";
|
||||
import { assignItemsFromConfiguration } from "#items/held-item-pool";
|
||||
import type { TrainerItemConfiguration } from "#items/trainer-item-data-types";
|
||||
|
||||
/**
|
||||
* Uses either `MODIFIER_OVERRIDE` in overrides.ts to set {@linkcode PersistentModifier}s for either:
|
||||
* - The player
|
||||
* - The enemy
|
||||
* @param isPlayer {@linkcode boolean} for whether the player (`true`) or enemy (`false`) is being overridden
|
||||
*/
|
||||
export function overrideTrainerItems(isPlayer = true): void {
|
||||
const trainerItemsOverride: TrainerItemConfiguration = isPlayer
|
||||
? Overrides.STARTING_TRAINER_ITEMS_OVERRIDE
|
||||
: Overrides.OPP_TRAINER_ITEMS_OVERRIDE;
|
||||
if (!trainerItemsOverride || trainerItemsOverride.length === 0 || !globalScene) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's the opponent, clear all of their current modifiers to avoid stacking
|
||||
if (!isPlayer) {
|
||||
globalScene.clearEnemyItems();
|
||||
}
|
||||
|
||||
globalScene.assignTrainerItemsFromConfiguration(trainerItemsOverride, isPlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses either `HELD_ITEMS_OVERRIDE` in overrides.ts to set {@linkcode PokemonHeldItemModifier}s for either:
|
||||
* - The first member of the player's team when starting a new game
|
||||
* - An enemy {@linkcode Pokemon} being spawned in
|
||||
* @param pokemon {@linkcode Pokemon} whose held items are being overridden
|
||||
* @param isPlayer {@linkcode boolean} for whether the {@linkcode pokemon} is the player's (`true`) or an enemy (`false`)
|
||||
*/
|
||||
export function overrideHeldItems(pokemon: Pokemon, isPlayer = true): void {
|
||||
const heldItemsOverride: HeldItemConfiguration = isPlayer
|
||||
? Overrides.STARTING_HELD_ITEMS_OVERRIDE
|
||||
: Overrides.OPP_HELD_ITEMS_OVERRIDE;
|
||||
if (!heldItemsOverride || heldItemsOverride.length === 0 || !globalScene) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isPlayer) {
|
||||
pokemon.heldItemManager.clearItems();
|
||||
}
|
||||
|
||||
assignItemsFromConfiguration(heldItemsOverride, pokemon);
|
||||
}
|
72
src/items/reward-defaults-tiers.ts
Normal file
72
src/items/reward-defaults-tiers.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { RewardId } from "#enums/reward-id";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
|
||||
export const rewardRarities = {
|
||||
[RewardId.POKEBALL]: RarityTier.COMMON,
|
||||
[RewardId.GREAT_BALL]: RarityTier.GREAT,
|
||||
[RewardId.ULTRA_BALL]: RarityTier.ULTRA,
|
||||
[RewardId.ROGUE_BALL]: RarityTier.ROGUE,
|
||||
[RewardId.MASTER_BALL]: RarityTier.MASTER,
|
||||
|
||||
[RewardId.VOUCHER]: RarityTier.GREAT,
|
||||
[RewardId.VOUCHER_PLUS]: RarityTier.ROGUE,
|
||||
[RewardId.VOUCHER_PREMIUM]: RarityTier.MASTER,
|
||||
|
||||
[RewardId.NUGGET]: RarityTier.GREAT,
|
||||
[RewardId.BIG_NUGGET]: RarityTier.ULTRA,
|
||||
[RewardId.RELIC_GOLD]: RarityTier.ROGUE,
|
||||
|
||||
[RewardId.RARE_CANDY]: RarityTier.COMMON,
|
||||
[RewardId.RARER_CANDY]: RarityTier.ULTRA,
|
||||
|
||||
[RewardId.EVOLUTION_ITEM]: RarityTier.GREAT,
|
||||
[RewardId.RARE_EVOLUTION_ITEM]: RarityTier.ULTRA,
|
||||
|
||||
[RewardId.POTION]: RarityTier.COMMON,
|
||||
[RewardId.SUPER_POTION]: RarityTier.COMMON,
|
||||
[RewardId.HYPER_POTION]: RarityTier.GREAT,
|
||||
[RewardId.MAX_POTION]: RarityTier.GREAT,
|
||||
[RewardId.FULL_HEAL]: RarityTier.GREAT,
|
||||
[RewardId.FULL_RESTORE]: RarityTier.GREAT,
|
||||
|
||||
[RewardId.REVIVE]: RarityTier.GREAT,
|
||||
[RewardId.MAX_REVIVE]: RarityTier.GREAT,
|
||||
[RewardId.SACRED_ASH]: RarityTier.GREAT,
|
||||
|
||||
[RewardId.ETHER]: RarityTier.COMMON,
|
||||
[RewardId.MAX_ETHER]: RarityTier.COMMON,
|
||||
|
||||
[RewardId.ELIXIR]: RarityTier.GREAT,
|
||||
[RewardId.MAX_ELIXIR]: RarityTier.GREAT,
|
||||
|
||||
[RewardId.PP_UP]: RarityTier.GREAT,
|
||||
[RewardId.PP_MAX]: RarityTier.ULTRA,
|
||||
|
||||
[RewardId.TM_COMMON]: RarityTier.COMMON,
|
||||
[RewardId.TM_GREAT]: RarityTier.GREAT,
|
||||
[RewardId.TM_ULTRA]: RarityTier.ULTRA,
|
||||
|
||||
[RewardId.MINT]: RarityTier.ULTRA,
|
||||
[RewardId.TERA_SHARD]: RarityTier.GREAT,
|
||||
[RewardId.MEMORY_MUSHROOM]: RarityTier.GREAT,
|
||||
[RewardId.DNA_SPLICERS]: RarityTier.MASTER,
|
||||
|
||||
[RewardId.SPECIES_STAT_BOOSTER]: RarityTier.GREAT,
|
||||
[RewardId.RARE_SPECIES_STAT_BOOSTER]: RarityTier.ULTRA,
|
||||
[RewardId.BASE_STAT_BOOSTER]: RarityTier.GREAT,
|
||||
[RewardId.ATTACK_TYPE_BOOSTER]: RarityTier.ULTRA,
|
||||
[RewardId.BERRY]: RarityTier.COMMON,
|
||||
|
||||
[RewardId.TEMP_STAT_STAGE_BOOSTER]: RarityTier.COMMON,
|
||||
[RewardId.LURE]: RarityTier.COMMON,
|
||||
[RewardId.SUPER_LURE]: RarityTier.GREAT,
|
||||
[RewardId.MAX_LURE]: RarityTier.ULTRA,
|
||||
|
||||
[RewardId.FORM_CHANGE_ITEM]: RarityTier.ULTRA,
|
||||
[RewardId.RARE_FORM_CHANGE_ITEM]: RarityTier.ROGUE,
|
||||
};
|
||||
|
||||
export function getRewardTier(reward: RewardId): RarityTier {
|
||||
const tier = rewardRarities[reward];
|
||||
return tier ?? RarityTier.LUXURY;
|
||||
}
|
340
src/items/reward-pool-utils.ts
Normal file
340
src/items/reward-pool-utils.ts
Normal file
@ -0,0 +1,340 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import Overrides from "#app/overrides";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import { RewardPoolType } from "#enums/reward-pool-type";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||
import type { RewardFunc, RewardPool, RewardPoolWeights } from "#types/rewards";
|
||||
import { isNullOrUndefined, pickWeightedIndex, randSeedInt } from "#utils/common";
|
||||
import { getPartyLuckValue } from "#utils/party";
|
||||
import { type Reward, RewardGenerator, RewardOption, type RewardOverride, TrainerItemReward } from "./reward";
|
||||
import { rewardPool, rewardPoolWeights } from "./reward-pools";
|
||||
import { getRewardDefaultTier } from "./reward-utils";
|
||||
|
||||
/*
|
||||
This file still contains several functions to generate rewards from pools. The hierarchy of these functions is explained here.
|
||||
|
||||
At the top of the food chain is `generatePlayerRewardOptions`, which is responsible for creating item rewards for the player.
|
||||
It can take a `CustomRewardSettings` to fix any number of rewards or tiers, then fills the remaining spots randomly.
|
||||
Note that this function generates `RewardOption` instances, not yet `Reward`s.
|
||||
Currently, there is only one reward pool, but in the future we will want to allow for custom pools.
|
||||
|
||||
The function `getNewRewardOption` is responsible for generating a single RewardOption from a given pool and set of weights.
|
||||
Note that, in the previous system, this function could in principle generate rewards for enemies, which was used in some
|
||||
cases to assign modifiers. This usage is now deprecated, as we have separate pools for held items and trainer items for enemies.
|
||||
|
||||
However, `getNewRewardOption` is not called directly by `generatePlayerRewardOptions`. Instead, it is filtered
|
||||
by `getRewardOptionWithRetry`, which also checks existing rewards to minimize the chance of duplicates.
|
||||
|
||||
Note that the pool contains `WeightedReward` instances, which contain either a `Reward` or a `RewardGenerator`.
|
||||
Once a pool entry is chosen, a specific `Reward` is generated accordingly and put in the returned `RewardOption`.
|
||||
|
||||
This will allow more customization in creating pools for challenges, MEs etc.
|
||||
*/
|
||||
|
||||
export interface CustomRewardSettings {
|
||||
guaranteedRarityTiers?: RarityTier[];
|
||||
guaranteedRewardOptions?: RewardOption[];
|
||||
/** If specified, will override the next X items to be auto-generated from specific reward functions (these don't have to be pre-genned). */
|
||||
guaranteedRewardFuncs?: RewardFunc[];
|
||||
/**
|
||||
* If set to `true`, will fill the remainder of shop items that were not overridden by the 3 options above, up to the `count` param value.
|
||||
* @example
|
||||
* ```ts
|
||||
* count = 4;
|
||||
* customRewardSettings = { guaranteedRarityTiers: [RarityTier.GREAT], fillRemaining: true };
|
||||
* ```
|
||||
* The first item in the shop will be `GREAT` tier, and the remaining `3` items will be generated normally.
|
||||
*
|
||||
* If `fillRemaining: false` in the same scenario, only 1 `GREAT` tier item will appear in the shop (regardless of the value of `count`).
|
||||
* @defaultValue `false`
|
||||
*/
|
||||
fillRemaining?: boolean;
|
||||
/** If specified, can adjust the amount of money required for a shop reroll. If set to a negative value, the shop will not allow rerolls at all. */
|
||||
rerollMultiplier?: number;
|
||||
/**
|
||||
* If `false`, will prevent set item tiers from upgrading via luck.
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
allowLuckUpgrades?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates weights for a {@linkcode RewardPool}. An array of weights is generated for each rarity tier. Weights can be 0.
|
||||
* @param pool - The pool for which weights must be generated
|
||||
* @param party - Party is required for generating the weights
|
||||
* @param rerollCount - (Optional) Needed for weights of vouchers.
|
||||
*/
|
||||
export function generateRewardPoolWeights(pool: RewardPool, party: Pokemon[], rerollCount = 0) {
|
||||
for (const tier of Object.keys(pool)) {
|
||||
const poolWeights = pool[tier].map(w => {
|
||||
if (w.reward instanceof TrainerItemReward) {
|
||||
const id = w.reward.itemId;
|
||||
if (globalScene.trainerItems.isMaxStack(id)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (typeof w.weight === "number") {
|
||||
return w.weight;
|
||||
}
|
||||
return w.weight(party, rerollCount);
|
||||
});
|
||||
rewardPoolWeights[tier] = poolWeights;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random RarityTier to draw rewards from the pool. The probabilities are:
|
||||
* 1/1024 (Master tier)
|
||||
* 12/1024 (Rogue tier)
|
||||
* 48/1024 (Ultra tier)
|
||||
* 195/1024 (Great tier)
|
||||
* 768/1024 (Common tier)
|
||||
* return {@linkcode RarityTier}
|
||||
*/
|
||||
function randomBaseTier(): RarityTier {
|
||||
const tierValue = randSeedInt(1024);
|
||||
|
||||
if (tierValue > 255) {
|
||||
return RarityTier.COMMON;
|
||||
}
|
||||
if (tierValue > 60) {
|
||||
return RarityTier.GREAT;
|
||||
}
|
||||
if (tierValue > 12) {
|
||||
return RarityTier.ULTRA;
|
||||
}
|
||||
if (tierValue) {
|
||||
return RarityTier.ROGUE;
|
||||
}
|
||||
return RarityTier.MASTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the upgrade count for a given rarity tier, based on the party luck. Will not update
|
||||
* if the pool would have no entries at the new rarity.
|
||||
* @param pool - RewardPool from which the reward will be generated
|
||||
* @param baseTier - The initial tier to upgrade
|
||||
* @param party - Party of the trainer using the item
|
||||
* return {@linkcode RarityTier}
|
||||
*/
|
||||
function getRarityUpgradeCount(pool: RewardPool, baseTier: RarityTier, party: Pokemon[]): RarityTier {
|
||||
let upgradeCount = 0;
|
||||
if (baseTier < RarityTier.MASTER) {
|
||||
const partyLuckValue = getPartyLuckValue(party);
|
||||
const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4));
|
||||
while (pool.hasOwnProperty(baseTier + upgradeCount + 1) && pool[baseTier + upgradeCount + 1].length) {
|
||||
if (randSeedInt(upgradeOdds) < 4) {
|
||||
upgradeCount++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return upgradeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates reward options for a {@linkcode SelectRewardPhase}
|
||||
* @param count - Determines the number of items to generate
|
||||
* @param party - Party is required for generating proper reward pools
|
||||
* @param rarityTiers - (Optional) If specified, rolls items in the specified tiers. Commonly used for tier-locking with Lock Capsule.
|
||||
* @param customRewardSettings - (Optional) See {@linkcode CustomRewardSettings}
|
||||
*/
|
||||
export function generatePlayerRewardOptions(
|
||||
count: number,
|
||||
party: PlayerPokemon[],
|
||||
rarityTiers?: RarityTier[],
|
||||
customRewardSettings?: CustomRewardSettings,
|
||||
): RewardOption[] {
|
||||
const options: RewardOption[] = [];
|
||||
const retryCount = Math.min(count * 5, 50);
|
||||
// TODO: Change this to allow for custom reward pools
|
||||
const pool = getRewardPoolForType(RewardPoolType.PLAYER);
|
||||
const weights = getRewardWeightsForType(RewardPoolType.PLAYER);
|
||||
if (!customRewardSettings) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const tier = rarityTiers && rarityTiers.length > i ? rarityTiers[i] : undefined;
|
||||
options.push(getRewardOptionWithRetry(pool, weights, options, retryCount, party, tier));
|
||||
}
|
||||
} else {
|
||||
// Guaranteed mod options first
|
||||
if (customRewardSettings?.guaranteedRewardOptions && customRewardSettings.guaranteedRewardOptions.length > 0) {
|
||||
options.push(...customRewardSettings.guaranteedRewardOptions!);
|
||||
}
|
||||
|
||||
// Guaranteed mod functions second
|
||||
if (customRewardSettings.guaranteedRewardFuncs && customRewardSettings.guaranteedRewardFuncs.length > 0) {
|
||||
customRewardSettings.guaranteedRewardFuncs!.forEach((mod, _i) => {
|
||||
const rewardId = Object.keys(allRewards).find(k => allRewards[k] === mod) as string;
|
||||
const guaranteedMod: Reward = allRewards[rewardId]?.();
|
||||
|
||||
// Populates item id and tier
|
||||
const guaranteedModTier = getRewardDefaultTier(guaranteedMod);
|
||||
|
||||
const modType = guaranteedMod instanceof RewardGenerator ? guaranteedMod.generateReward(party) : guaranteedMod;
|
||||
if (modType) {
|
||||
const option = new RewardOption(modType, 0, guaranteedModTier);
|
||||
options.push(option);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Guaranteed tiers third
|
||||
if (customRewardSettings.guaranteedRarityTiers && customRewardSettings.guaranteedRarityTiers.length > 0) {
|
||||
const allowLuckUpgrades = customRewardSettings.allowLuckUpgrades ?? true;
|
||||
for (const tier of customRewardSettings.guaranteedRarityTiers) {
|
||||
options.push(getRewardOptionWithRetry(pool, weights, options, retryCount, party, tier, allowLuckUpgrades));
|
||||
}
|
||||
}
|
||||
|
||||
// Fill remaining
|
||||
if (options.length < count && customRewardSettings.fillRemaining) {
|
||||
while (options.length < count) {
|
||||
options.push(getRewardOptionWithRetry(pool, weights, options, retryCount, party, undefined));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Applies overrides for testing
|
||||
overridePlayerRewardOptions(options, party);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will generate a {@linkcode RewardOption} from the {@linkcode RewardPoolType.PLAYER} pool, attempting to retry duplicated items up to retryCount
|
||||
* @param pool - {@linkcode RewardPool} to generate items from
|
||||
* @param weights - {@linkcode RewardPoolWeights} to use when generating items
|
||||
* @param existingOptions Currently generated options
|
||||
* @param retryCount How many times to retry before allowing a dupe item
|
||||
* @param party Current player party, used to calculate items in the pool
|
||||
* @param tier If specified will generate item of tier
|
||||
* @param allowLuckUpgrades `true` to allow items to upgrade tiers (the little animation that plays and is affected by luck)
|
||||
*/
|
||||
function getRewardOptionWithRetry(
|
||||
pool: RewardPool,
|
||||
weights: RewardPoolWeights,
|
||||
existingOptions: RewardOption[],
|
||||
retryCount: number,
|
||||
party: PlayerPokemon[],
|
||||
tier?: RarityTier,
|
||||
allowLuckUpgrades?: boolean,
|
||||
): RewardOption {
|
||||
allowLuckUpgrades = allowLuckUpgrades ?? true;
|
||||
let candidate = getNewRewardOption(pool, weights, party, tier, undefined, 0, allowLuckUpgrades);
|
||||
let r = 0;
|
||||
while (
|
||||
existingOptions.length &&
|
||||
++r < retryCount &&
|
||||
//TODO: Improve this condition to refine what counts as a dupe
|
||||
existingOptions.filter(o => o.type.name === candidate?.type.name || o.type.group === candidate?.type.group).length
|
||||
) {
|
||||
console.log("Retry count:", r);
|
||||
console.log(candidate?.type.group);
|
||||
console.log(candidate?.type.name);
|
||||
console.log(existingOptions.filter(o => o.type.name === candidate?.type.name).length);
|
||||
console.log(existingOptions.filter(o => o.type.group === candidate?.type.group).length);
|
||||
candidate = getNewRewardOption(
|
||||
pool,
|
||||
weights,
|
||||
party,
|
||||
candidate?.type.tier ?? tier,
|
||||
candidate?.upgradeCount,
|
||||
0,
|
||||
allowLuckUpgrades,
|
||||
);
|
||||
}
|
||||
return candidate!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a Reward from the specified pool
|
||||
* @param pool - {@linkcode RewardPool} to generate items from
|
||||
* @param weights - {@linkcode RewardPoolWeights} to use when generating items
|
||||
* @param party - party of the trainer using the item
|
||||
* @param baseTier - If specified, will override the initial tier of an item (can still upgrade with luck)
|
||||
* @param upgradeCount - If defined, means that this is a new Reward being generated to override another via luck upgrade. Used for recursive logic
|
||||
* @param retryCount - Max allowed tries before the next tier down is checked for a valid Reward
|
||||
* @param allowLuckUpgrades - Default true. If false, will not allow Reward to randomly upgrade to next tier
|
||||
*/
|
||||
function getNewRewardOption(
|
||||
pool: RewardPool,
|
||||
weights: RewardPoolWeights,
|
||||
party: PlayerPokemon[],
|
||||
baseTier?: RarityTier,
|
||||
upgradeCount?: number,
|
||||
retryCount = 0,
|
||||
allowLuckUpgrades = true,
|
||||
): RewardOption | null {
|
||||
let tier = 0;
|
||||
if (isNullOrUndefined(baseTier)) {
|
||||
baseTier = randomBaseTier();
|
||||
}
|
||||
if (isNullOrUndefined(upgradeCount)) {
|
||||
upgradeCount = allowLuckUpgrades ? getRarityUpgradeCount(pool, baseTier, party) : 0;
|
||||
tier = baseTier + upgradeCount;
|
||||
} else {
|
||||
tier = baseTier;
|
||||
}
|
||||
|
||||
const tierWeights = weights[tier];
|
||||
const index = pickWeightedIndex(tierWeights);
|
||||
|
||||
if (index === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let reward: Reward | RewardGenerator | null = pool[tier][index].reward;
|
||||
if (reward instanceof RewardGenerator) {
|
||||
reward = (reward as RewardGenerator).generateReward(party);
|
||||
if (reward === null) {
|
||||
console.log(RarityTier[tier], upgradeCount);
|
||||
return getNewRewardOption(pool, weights, party, tier, upgradeCount, ++retryCount);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(reward);
|
||||
|
||||
return new RewardOption(reward as Reward, upgradeCount!, tier); // TODO: is this bang correct?
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the {@linkcode Reward} of the entries within {@linkcode options} with any
|
||||
* {@linkcode RewardOverride} entries listed in {@linkcode Overrides.REWARD_OVERRIDE}
|
||||
* up to the smallest amount of entries between {@linkcode options} and the override array.
|
||||
* @param options Array of naturally rolled {@linkcode RewardOption}s
|
||||
* @param party Array of the player's current party
|
||||
*/
|
||||
export function overridePlayerRewardOptions(options: RewardOption[], party: PlayerPokemon[]) {
|
||||
const minLength = Math.min(options.length, Overrides.REWARD_OVERRIDE.length);
|
||||
for (let i = 0; i < minLength; i++) {
|
||||
const override: RewardOverride = Overrides.REWARD_OVERRIDE[i];
|
||||
const rewardFunc = allRewards[override.name];
|
||||
let reward: Reward | RewardGenerator | null = rewardFunc();
|
||||
|
||||
if (reward instanceof RewardGenerator) {
|
||||
const pregenArgs = "type" in override && override.type !== null ? [override.type] : undefined;
|
||||
reward = reward.generateReward(party, pregenArgs);
|
||||
}
|
||||
|
||||
if (reward) {
|
||||
options[i].type = reward;
|
||||
options[i].tier = getRewardDefaultTier(reward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getRewardPoolForType(poolType: RewardPoolType): RewardPool {
|
||||
switch (poolType) {
|
||||
case RewardPoolType.PLAYER:
|
||||
return rewardPool;
|
||||
}
|
||||
}
|
||||
|
||||
export function getRewardWeightsForType(poolType: RewardPoolType): RewardPoolWeights {
|
||||
switch (poolType) {
|
||||
case RewardPoolType.PLAYER:
|
||||
return rewardPoolWeights;
|
||||
}
|
||||
}
|
9
src/items/reward-pools.ts
Normal file
9
src/items/reward-pools.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Contains modifier pools for different contexts in the game.
|
||||
* Can be safely imported without worrying about circular dependencies.
|
||||
*/
|
||||
|
||||
import type { RewardPool, RewardPoolWeights } from "#types/rewards";
|
||||
|
||||
export const rewardPool: RewardPool = {};
|
||||
export const rewardPoolWeights: RewardPoolWeights = {};
|
115
src/items/reward-utils.ts
Normal file
115
src/items/reward-utils.ts
Normal file
@ -0,0 +1,115 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { allRewards } from "#data/data-lists";
|
||||
import type { HeldItemId } from "#enums/held-item-id";
|
||||
import { getRewardCategory, RewardCategoryId, RewardId } from "#enums/reward-id";
|
||||
import type { RarityTier } from "#enums/reward-tier";
|
||||
import type { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import type { RewardFunc, RewardPoolId } from "#types/rewards";
|
||||
import { getHeldItemTier } from "./held-item-default-tiers";
|
||||
import {
|
||||
type HeldItemReward,
|
||||
type PokemonMoveReward,
|
||||
type RememberMoveReward,
|
||||
type Reward,
|
||||
RewardGenerator,
|
||||
RewardOption,
|
||||
type TmReward,
|
||||
type TrainerItemReward,
|
||||
} from "./reward";
|
||||
import { getRewardTier } from "./reward-defaults-tiers";
|
||||
import { getTrainerItemTier } from "./trainer-item-default-tiers";
|
||||
|
||||
export function isTmReward(reward: Reward): reward is TmReward {
|
||||
return getRewardCategory(reward.id) === RewardCategoryId.TM;
|
||||
}
|
||||
|
||||
export function isMoveReward(reward: Reward): reward is PokemonMoveReward {
|
||||
const categoryId = getRewardCategory(reward.id);
|
||||
return categoryId === RewardCategoryId.ETHER || categoryId === RewardCategoryId.PP_UP;
|
||||
}
|
||||
|
||||
export function isRememberMoveReward(reward: Reward): reward is RememberMoveReward {
|
||||
return reward.id === RewardId.MEMORY_MUSHROOM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a Reward from a given function
|
||||
* @param rewardFunc
|
||||
* @param pregenArgs Can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
||||
*/
|
||||
export function generateReward(rewardFunc: RewardFunc, pregenArgs?: any[]): Reward | null {
|
||||
const reward = rewardFunc();
|
||||
return reward instanceof RewardGenerator ? reward.generateReward(globalScene.getPlayerParty(), pregenArgs) : reward;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a Reward Option from a given function
|
||||
* @param rewardFunc
|
||||
* @param pregenArgs - can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
||||
*/
|
||||
export function generateRewardOption(rewardFunc: RewardFunc, pregenArgs?: any[]): RewardOption | null {
|
||||
const reward = generateReward(rewardFunc, pregenArgs);
|
||||
if (reward) {
|
||||
const tier = getRewardDefaultTier(reward);
|
||||
return new RewardOption(reward, 0, tier);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the default rarity tier for a given reward. For unique held item or trainer item rewards,
|
||||
* falls back to the default rarity tier for the item.
|
||||
* @param reward The {@linkcode Reward} to determine the tier for.
|
||||
*/
|
||||
export function getRewardDefaultTier(reward: Reward): RarityTier {
|
||||
if (reward.id === RewardId.HELD_ITEM) {
|
||||
return getHeldItemTier((reward as HeldItemReward).itemId);
|
||||
}
|
||||
if (reward.id === RewardId.TRAINER_ITEM) {
|
||||
return getTrainerItemTier((reward as TrainerItemReward).itemId);
|
||||
}
|
||||
return getRewardTier(reward.id);
|
||||
}
|
||||
|
||||
export function getPlayerShopRewardOptionsForWave(waveIndex: number, baseCost: number): RewardOption[] {
|
||||
if (!(waveIndex % 10)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const options = [
|
||||
[
|
||||
new RewardOption(allRewards.POTION(), 0, baseCost * 0.2),
|
||||
new RewardOption(allRewards.ETHER(), 0, baseCost * 0.4),
|
||||
new RewardOption(allRewards.REVIVE(), 0, baseCost * 2),
|
||||
],
|
||||
[
|
||||
new RewardOption(allRewards.SUPER_POTION(), 0, baseCost * 0.45),
|
||||
new RewardOption(allRewards.FULL_HEAL(), 0, baseCost),
|
||||
],
|
||||
[new RewardOption(allRewards.ELIXIR(), 0, baseCost), new RewardOption(allRewards.MAX_ETHER(), 0, baseCost)],
|
||||
[
|
||||
new RewardOption(allRewards.HYPER_POTION(), 0, baseCost * 0.8),
|
||||
new RewardOption(allRewards.MAX_REVIVE(), 0, baseCost * 2.75),
|
||||
new RewardOption(allRewards.MEMORY_MUSHROOM(), 0, baseCost * 4),
|
||||
],
|
||||
[
|
||||
new RewardOption(allRewards.MAX_POTION(), 0, baseCost * 1.5),
|
||||
new RewardOption(allRewards.MAX_ELIXIR(), 0, baseCost * 2.5),
|
||||
],
|
||||
[new RewardOption(allRewards.FULL_RESTORE(), 0, baseCost * 2.25)],
|
||||
[new RewardOption(allRewards.SACRED_ASH(), 0, baseCost * 10)],
|
||||
];
|
||||
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
||||
}
|
||||
|
||||
export function isRewardId(id: RewardPoolId): id is RewardId {
|
||||
return id > 0x2000;
|
||||
}
|
||||
|
||||
export function isTrainerItemId(id: RewardPoolId): id is TrainerItemId {
|
||||
return id > 0x1000 && id < 0x2000;
|
||||
}
|
||||
|
||||
export function isHeldItemId(id: RewardPoolId): id is HeldItemId {
|
||||
return id < 0x1000;
|
||||
}
|
1852
src/items/reward.ts
Normal file
1852
src/items/reward.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
// TODO: move to `src/@types/`
|
||||
import type { RewardTier } from "#enums/reward-tier";
|
||||
import type { RarityTier } from "#enums/reward-tier";
|
||||
import type { TrainerItemId } from "#enums/trainer-item-id";
|
||||
|
||||
export type TrainerItemData = {
|
||||
@ -28,7 +28,7 @@ type TrainerItemPoolEntry = {
|
||||
export type TrainerItemPool = TrainerItemPoolEntry[];
|
||||
|
||||
export type TrainerItemTieredPool = {
|
||||
[key in RewardTier]?: TrainerItemPool;
|
||||
[key in RarityTier]?: TrainerItemPool;
|
||||
};
|
||||
|
||||
export function isTrainerItemPool(value: any): value is TrainerItemPool {
|
||||
|
50
src/items/trainer-item-default-tiers.ts
Normal file
50
src/items/trainer-item-default-tiers.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||
|
||||
export const trainerItemRarities = {
|
||||
[TrainerItemId.MAP]: RarityTier.COMMON,
|
||||
[TrainerItemId.IV_SCANNER]: RarityTier.ULTRA,
|
||||
[TrainerItemId.LOCK_CAPSULE]: RarityTier.ROGUE,
|
||||
[TrainerItemId.MEGA_BRACELET]: RarityTier.ROGUE,
|
||||
[TrainerItemId.DYNAMAX_BAND]: RarityTier.ROGUE,
|
||||
[TrainerItemId.TERA_ORB]: RarityTier.ULTRA,
|
||||
|
||||
[TrainerItemId.GOLDEN_POKEBALL]: RarityTier.LUXURY,
|
||||
|
||||
[TrainerItemId.OVAL_CHARM]: RarityTier.LUXURY,
|
||||
[TrainerItemId.EXP_SHARE]: RarityTier.ULTRA,
|
||||
[TrainerItemId.EXP_BALANCE]: RarityTier.LUXURY,
|
||||
|
||||
[TrainerItemId.CANDY_JAR]: RarityTier.ULTRA,
|
||||
[TrainerItemId.BERRY_POUCH]: RarityTier.ROGUE,
|
||||
|
||||
[TrainerItemId.HEALING_CHARM]: RarityTier.MASTER,
|
||||
[TrainerItemId.EXP_CHARM]: RarityTier.ULTRA,
|
||||
[TrainerItemId.SUPER_EXP_CHARM]: RarityTier.ROGUE,
|
||||
[TrainerItemId.GOLDEN_EXP_CHARM]: RarityTier.LUXURY,
|
||||
[TrainerItemId.AMULET_COIN]: RarityTier.ULTRA,
|
||||
|
||||
[TrainerItemId.ABILITY_CHARM]: RarityTier.ULTRA,
|
||||
[TrainerItemId.SHINY_CHARM]: RarityTier.MASTER,
|
||||
[TrainerItemId.CATCHING_CHARM]: RarityTier.ULTRA,
|
||||
|
||||
[TrainerItemId.BLACK_SLUDGE]: RarityTier.LUXURY,
|
||||
[TrainerItemId.GOLDEN_BUG_NET]: RarityTier.LUXURY,
|
||||
|
||||
[TrainerItemId.LURE]: RarityTier.COMMON,
|
||||
[TrainerItemId.SUPER_LURE]: RarityTier.GREAT,
|
||||
[TrainerItemId.MAX_LURE]: RarityTier.ULTRA,
|
||||
|
||||
[TrainerItemId.X_ATTACK]: RarityTier.COMMON,
|
||||
[TrainerItemId.X_DEFENSE]: RarityTier.COMMON,
|
||||
[TrainerItemId.X_SP_ATK]: RarityTier.COMMON,
|
||||
[TrainerItemId.X_SP_DEF]: RarityTier.COMMON,
|
||||
[TrainerItemId.X_SPEED]: RarityTier.COMMON,
|
||||
[TrainerItemId.X_ACCURACY]: RarityTier.COMMON,
|
||||
[TrainerItemId.DIRE_HIT]: RarityTier.GREAT,
|
||||
};
|
||||
|
||||
export function getTrainerItemTier(item: TrainerItemId): RarityTier {
|
||||
const tier = trainerItemRarities[item];
|
||||
return tier ?? RarityTier.LUXURY;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { allTrainerItems } from "#data/data-lists";
|
||||
import { RewardTier } from "#enums/reward-tier";
|
||||
import { RarityTier } from "#enums/reward-tier";
|
||||
import type { TrainerItemId } from "#enums/trainer-item-id";
|
||||
import type { TrainerItemPool, TrainerItemTieredPool } from "#items/trainer-item-data-types";
|
||||
import type { TrainerItemManager } from "#items/trainer-item-manager";
|
||||
@ -29,13 +29,13 @@ export function getNewTrainerItemFromPool(pool: TrainerItemPool, manager: Traine
|
||||
return entry as TrainerItemId;
|
||||
}
|
||||
|
||||
export function assignEnemyBuffTokenForWave(tier: RewardTier) {
|
||||
export function assignEnemyBuffTokenForWave(tier: RarityTier) {
|
||||
let tierStackCount: number;
|
||||
switch (tier) {
|
||||
case RewardTier.ULTRA:
|
||||
case RarityTier.ULTRA:
|
||||
tierStackCount = 5;
|
||||
break;
|
||||
case RewardTier.GREAT:
|
||||
case RarityTier.GREAT:
|
||||
tierStackCount = 3;
|
||||
break;
|
||||
default:
|
||||
|
@ -297,9 +297,9 @@ export class DoubleBattleChanceBoosterTrainerItem extends LapsingTrainerItem {
|
||||
}
|
||||
}
|
||||
|
||||
interface TempStatToTrainerItemMap {
|
||||
[key: number]: TrainerItemId;
|
||||
}
|
||||
type TempStatToTrainerItemMap = {
|
||||
[key in TempBattleStat]: TrainerItemId;
|
||||
};
|
||||
|
||||
export const tempStatToTrainerItem: TempStatToTrainerItemMap = {
|
||||
[Stat.ATK]: TrainerItemId.X_ATTACK,
|
||||
|
@ -15,9 +15,9 @@ import { getBiomeHasProps } from "#field/arena";
|
||||
import { initHeldItems } from "#items/all-held-items";
|
||||
import { initTrainerItems } from "#items/all-trainer-items";
|
||||
import { initHeldItemPools } from "#items/init-held-item-pools";
|
||||
import { initRewardPools } from "#items/init-reward-pools";
|
||||
import { initTrainerItemPools } from "#items/init-trainer-item-pools";
|
||||
import { initModifierPools } from "#modifiers/init-modifier-pools";
|
||||
import { initModifierTypes } from "#modifiers/modifier-type";
|
||||
import { initRewards } from "#items/reward";
|
||||
import { initMoves } from "#moves/move";
|
||||
import { initMysteryEncounters } from "#mystery-encounters/mystery-encounters";
|
||||
import { CacheBustedLoaderPlugin } from "#plugins/cache-busted-loader-plugin";
|
||||
@ -370,8 +370,8 @@ export class LoadingScene extends SceneBase {
|
||||
|
||||
this.loadLoadingScreen();
|
||||
|
||||
initModifierTypes();
|
||||
initModifierPools();
|
||||
initRewards();
|
||||
initRewardPools();
|
||||
initHeldItemPools();
|
||||
initTrainerItemPools();
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
/*
|
||||
* Contains modifier pools for different contexts in the game.
|
||||
* Can be safely imported without worrying about circular dependencies.
|
||||
*/
|
||||
|
||||
import type { ModifierPool } from "#types/modifier-types";
|
||||
|
||||
export const modifierPool: ModifierPool = {};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user