mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-04 07:22:19 +02:00
[WIP] move modifier stuff around
This commit is contained in:
parent
7beb5446e7
commit
5c9697e36a
32
src/@types/modifier-types.ts
Normal file
32
src/@types/modifier-types.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Re-exports of all the types defined in the modifier module.
|
||||
*/
|
||||
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import type { ModifierConstructorMap } from "#app/modifier/modifier";
|
||||
import type { ModifierType, WeightedModifierType } from "#app/modifier/modifier-type";
|
||||
export type ModifierTypeFunc = () => ModifierType;
|
||||
export type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: number) => number;
|
||||
|
||||
export type { ModifierConstructorMap } from "#app/modifier/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[];
|
||||
}
|
@ -58,13 +58,13 @@ import {
|
||||
getEnemyModifierTypesForWave,
|
||||
getLuckString,
|
||||
getLuckTextTint,
|
||||
getModifierPoolForType,
|
||||
getModifierType,
|
||||
getPartyLuckValue,
|
||||
ModifierPoolType,
|
||||
modifierTypes,
|
||||
PokemonHeldItemModifierType,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { getModifierPoolForType } from "./utils/modifier-pool-utils";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import AbilityBar from "#app/ui/ability-bar";
|
||||
import { applyAbAttrs, applyPostBattleInitAbAttrs, applyPostItemLostAbAttrs } from "./data/abilities/apply-ab-attrs";
|
||||
import { allAbilities } from "./data/data-lists";
|
||||
|
@ -30,7 +30,7 @@ import i18next from "#app/plugins/i18n";
|
||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import type { CustomModifierSettings } from "#app/modifier/modifier-type";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
|
||||
|
@ -21,7 +21,7 @@ import { TrainerType } from "#enums/trainer-type";
|
||||
import { Nature } from "#enums/nature";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import { TypeColor, TypeShadow } from "#enums/color";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { pokemonFormChanges } from "./pokemon-forms";
|
||||
import { pokemonEvolutions } from "./balance/pokemon-evolutions";
|
||||
|
@ -51,7 +51,7 @@ import {
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import { TerrainType } from "../terrain";
|
||||
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { Command } from "#enums/command";
|
||||
import i18next from "i18next";
|
||||
import type { Localizable } from "#app/@types/locales";
|
||||
|
@ -19,7 +19,7 @@ import i18next from "i18next";
|
||||
import type { IEggOptions } from "#app/data/egg";
|
||||
import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
|
||||
|
@ -12,7 +12,8 @@ import {
|
||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import type { BerryModifierType, ModifierTypeOption } from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||
import { modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { randSeedInt } from "#app/utils/common";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
|
@ -50,7 +50,7 @@ import {
|
||||
import i18next from "i18next";
|
||||
import MoveInfoOverlay from "#app/ui/move-info-overlay";
|
||||
import { allMoves } from "#app/data/data-lists";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
|
||||
|
@ -11,9 +11,10 @@ import {
|
||||
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
||||
import { TrainerPartyCompoundTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType, modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
|
@ -2,7 +2,7 @@ import {
|
||||
leaveEncounterWithoutBattle,
|
||||
setEncounterRewards,
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import type { ModifierTypeFunc } from "#app/modifier/modifier-type";
|
||||
import type { ModifierTypeFunc } from "#app/@types/modifier-types";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { randSeedInt } from "#app/utils/common";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
|
@ -9,13 +9,13 @@ import {
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import type { ModifierTypeOption } from "#app/modifier/modifier-type";
|
||||
import {
|
||||
getPlayerModifierTypeOptions,
|
||||
ModifierPoolType,
|
||||
regenerateModifierPoolThresholds,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||
|
@ -4,14 +4,14 @@ import {
|
||||
setEncounterRewards,
|
||||
} from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { TrainerSlot } from "#enums/trainer-slot";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { MusicPreference } from "#app/system/settings/settings";
|
||||
import type { ModifierTypeOption } from "#app/modifier/modifier-type";
|
||||
import {
|
||||
getPlayerModifierTypeOptions,
|
||||
ModifierPoolType,
|
||||
regenerateModifierPoolThresholds,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
|
||||
|
@ -7,7 +7,7 @@ import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
||||
import { trainerPartyTemplates } from "#app/data/trainers/TrainerPartyTemplate";
|
||||
import { TrainerPartyCompoundTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { randSeedInt } from "#app/utils/common";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
|
@ -28,7 +28,7 @@ import { applyPostBattleInitAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
import i18next from "i18next";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
|
||||
|
@ -21,7 +21,7 @@ import { HitHealModifier, PokemonHeldItemModifier, TurnHealModifier } from "#app
|
||||
import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { BattlerIndex } from "#enums/battler-index";
|
||||
|
@ -34,7 +34,7 @@ import {
|
||||
import { getLevelTotalExp } from "#app/data/exp";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
|
@ -17,12 +17,12 @@ import { FieldPosition } from "#enums/field-position";
|
||||
import type { CustomModifierSettings, ModifierType } from "#app/modifier/modifier-type";
|
||||
import {
|
||||
getPartyLuckValue,
|
||||
ModifierPoolType,
|
||||
ModifierTypeGenerator,
|
||||
ModifierTypeOption,
|
||||
modifierTypes,
|
||||
regenerateModifierPoolThresholds,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import type PokemonData from "#app/system/pokemon-data";
|
||||
import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
|
||||
import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { CriticalCatchChanceBoosterModifier } from "#app/modifier/modifier";
|
||||
import { NumberHolder } from "#app/utils/common";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import i18next from "i18next";
|
||||
@ -94,7 +93,7 @@ export function getCriticalCaptureChance(modifiedCatchRate: number): number {
|
||||
}
|
||||
const dexCount = globalScene.gameData.getSpeciesCount(d => !!d.caughtAttr);
|
||||
const catchingCharmMultiplier = new NumberHolder(1);
|
||||
globalScene.findModifier(m => m instanceof CriticalCatchChanceBoosterModifier)?.apply(catchingCharmMultiplier);
|
||||
globalScene.findModifier(m => m.is("CriticalCatchChanceBoosterModifier"))?.apply(catchingCharmMultiplier);
|
||||
const dexMultiplier =
|
||||
globalScene.gameMode.isDaily || dexCount > 800
|
||||
? 2.5
|
||||
|
@ -37,7 +37,7 @@ import { timedEventManager } from "#app/global-event-manager";
|
||||
// Type imports
|
||||
import type { PokemonSpeciesFilter } from "#app/data/pokemon-species";
|
||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||
import type { ModifierTypeFunc } from "#app/modifier/modifier-type";
|
||||
import type { ModifierTypeFunc } from "#app/@types/modifier-types";
|
||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||
import type { EvilTeam } from "./evil-admin-trainer-pools";
|
||||
import type {
|
||||
|
7
src/enums/modifier-pool-type.ts
Normal file
7
src/enums/modifier-pool-type.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export enum ModifierPoolType {
|
||||
PLAYER,
|
||||
WILD,
|
||||
TRAINER,
|
||||
ENEMY_BUFF,
|
||||
DAILY_STARTER
|
||||
}
|
@ -154,7 +154,7 @@ import type { TrainerSlot } from "#enums/trainer-slot";
|
||||
import Overrides from "#app/overrides";
|
||||
import i18next from "i18next";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
|
@ -21,6 +21,7 @@ import { initVouchers } from "#app/system/voucher";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
import { initMysteryEncounters } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { timedEventManager } from "./global-event-manager";
|
||||
import { initModifierPools } from "./modifier/init-modifier-pools";
|
||||
|
||||
export class LoadingScene extends SceneBase {
|
||||
public static readonly KEY = "loading";
|
||||
@ -363,6 +364,8 @@ export class LoadingScene extends SceneBase {
|
||||
|
||||
this.loadLoadingScreen();
|
||||
|
||||
initModifierPools();
|
||||
|
||||
initAchievements();
|
||||
initVouchers();
|
||||
initStatsKeys();
|
||||
|
853
src/modifier/init-modifier-pools.ts
Normal file
853
src/modifier/init-modifier-pools.ts
Normal file
@ -0,0 +1,853 @@
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import {
|
||||
dailyStarterModifierPool,
|
||||
enemyBuffModifierPool,
|
||||
modifierPool,
|
||||
trainerModifierPool,
|
||||
wildModifierPool,
|
||||
} from "#app/modifier/modifier-pools";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import {
|
||||
DoubleBattleChanceBoosterModifier,
|
||||
ResetNegativeStatStageModifier,
|
||||
SpeciesCritBoosterModifier,
|
||||
TurnStatusEffectModifier,
|
||||
} from "./modifier";
|
||||
import { WeightedModifierType } from "./modifier-type";
|
||||
import { ModifierTier } from "../enums/modifier-tier";
|
||||
import type { WeightedModifierTypeWeightFunc } from "#app/@types/modifier-types";
|
||||
import { modifierTypes } from "./modifier-type";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { BerryModifier } from "./modifier";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { timedEventManager } from "#app/global-event-manager";
|
||||
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
|
||||
import { Unlockables } from "#app/system/unlockables";
|
||||
import { isNullOrUndefined } from "#app/utils/common";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball";
|
||||
|
||||
/**
|
||||
* Initialize the wild modifier pool
|
||||
*/
|
||||
function initWildModifierPool() {
|
||||
wildModifierPool[ModifierTier.COMMON] = [new WeightedModifierType(modifierTypes.BERRY, 1)].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
});
|
||||
wildModifierPool[ModifierTier.GREAT] = [new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 1)].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
});
|
||||
wildModifierPool[ModifierTier.ULTRA] = [
|
||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB, 0),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
});
|
||||
wildModifierPool[ModifierTier.ROGUE] = [new WeightedModifierType(modifierTypes.LUCKY_EGG, 4)].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
});
|
||||
wildModifierPool[ModifierTier.MASTER] = [new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1)].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the common modifier pool
|
||||
*/
|
||||
function initCommonModifierPool() {
|
||||
modifierPool[ModifierTier.COMMON] = [
|
||||
new WeightedModifierType(modifierTypes.POKEBALL, () => (hasMaximumBalls(PokeballType.POKEBALL) ? 0 : 6), 6),
|
||||
new WeightedModifierType(modifierTypes.RARE_CANDY, 2),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 10 && p.getHpRatio() <= 0.875 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.SUPER_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 25 && p.getHpRatio() <= 0.75 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.ETHER,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_ETHER,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.LURE, lureWeightFunc(10, 2)),
|
||||
new WeightedModifierType(modifierTypes.TEMP_STAT_STAGE_BOOSTER, 4),
|
||||
new WeightedModifierType(modifierTypes.BERRY, 2),
|
||||
new WeightedModifierType(modifierTypes.TM_COMMON, 2),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Great modifier pool
|
||||
*/
|
||||
function initGreatModifierPool() {
|
||||
modifierPool[ModifierTier.GREAT] = [
|
||||
new WeightedModifierType(modifierTypes.GREAT_BALL, () => (hasMaximumBalls(PokeballType.GREAT_BALL) ? 0 : 6), 6),
|
||||
new WeightedModifierType(modifierTypes.PP_UP, 2),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FULL_HEAL,
|
||||
(party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!!p.status &&
|
||||
!p.getHeldItems().some(i => {
|
||||
if (i instanceof TurnStatusEffectModifier) {
|
||||
return (i as TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return statusEffectPartyMemberCount * 6;
|
||||
},
|
||||
18,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.REVIVE,
|
||||
(party: Pokemon[]) => {
|
||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||
return faintedPartyMemberCount * 9;
|
||||
},
|
||||
27,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_REVIVE,
|
||||
(party: Pokemon[]) => {
|
||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||
return faintedPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.SACRED_ASH,
|
||||
(party: Pokemon[]) => {
|
||||
return party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
||||
},
|
||||
1,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.HYPER_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.625 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.5 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FULL_RESTORE,
|
||||
(party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!!p.status &&
|
||||
!p.getHeldItems().some(i => {
|
||||
if (i instanceof TurnStatusEffectModifier) {
|
||||
return (i as TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
const thresholdPartyMemberCount = Math.floor(
|
||||
(Math.min(party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.5 && !p.isFainted()).length, 3) +
|
||||
statusEffectPartyMemberCount) /
|
||||
2,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.ELIXIR,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_ELIXIR,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.DIRE_HIT, 4),
|
||||
new WeightedModifierType(modifierTypes.SUPER_LURE, lureWeightFunc(15, 4)),
|
||||
new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)),
|
||||
new WeightedModifierType(modifierTypes.SPECIES_STAT_BOOSTER, 4),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.EVOLUTION_ITEM,
|
||||
() => {
|
||||
return Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 15), 8);
|
||||
},
|
||||
8,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.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,
|
||||
(party: Pokemon[]) => {
|
||||
if (!party.find(p => p.getLearnableLevelMoves().length)) {
|
||||
return 0;
|
||||
}
|
||||
const highestPartyLevel = party
|
||||
.map(p => p.level)
|
||||
.reduce((highestLevel: number, level: number) => Math.max(highestLevel, level), 1);
|
||||
return Math.min(Math.ceil(highestPartyLevel / 20), 4);
|
||||
},
|
||||
4,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3),
|
||||
new WeightedModifierType(modifierTypes.TERA_SHARD, (party: Pokemon[]) =>
|
||||
party.filter(
|
||||
p =>
|
||||
!(p.hasSpecies(SpeciesId.TERAPAGOS) || p.hasSpecies(SpeciesId.OGERPON) || p.hasSpecies(SpeciesId.SHEDINJA)),
|
||||
).length > 0
|
||||
? 1
|
||||
: 0,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.DNA_SPLICERS,
|
||||
(party: Pokemon[]) => {
|
||||
if (party.filter(p => !p.fusionSpecies).length > 1) {
|
||||
if (globalScene.gameMode.isSplicedOnly) {
|
||||
return 4;
|
||||
}
|
||||
if (globalScene.gameMode.isClassic && timedEventManager.areFusionsBoosted()) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
4,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.VOUCHER,
|
||||
(_party: Pokemon[], rerollCount: number) => (!globalScene.gameMode.isDaily ? Math.max(1 - rerollCount, 0) : 0),
|
||||
1,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Ultra modifier pool
|
||||
*/
|
||||
function initUltraModifierPool() {
|
||||
modifierPool[ModifierTier.ULTRA] = [
|
||||
new WeightedModifierType(modifierTypes.ULTRA_BALL, () => (hasMaximumBalls(PokeballType.ULTRA_BALL) ? 0 : 15), 15),
|
||||
new WeightedModifierType(modifierTypes.MAX_LURE, lureWeightFunc(30, 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,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 15) * 4, 32),
|
||||
32,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.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[]) => {
|
||||
const { gameMode, gameData } = globalScene;
|
||||
if (gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) {
|
||||
return party.some(p => {
|
||||
// Check if Pokemon's species (or fusion species, if applicable) can evolve or if they're G-Max'd
|
||||
if (
|
||||
!p.isMax() &&
|
||||
(p.getSpeciesForm(true).speciesId in pokemonEvolutions ||
|
||||
(p.isFusion() && p.getFusionSpeciesForm(true).speciesId in pokemonEvolutions))
|
||||
) {
|
||||
// Check if Pokemon is already holding an Eviolite
|
||||
return !p.getHeldItems().some(i => i.type.id === "EVIOLITE");
|
||||
}
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
}
|
||||
return 0;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.RARE_SPECIES_STAT_BOOSTER, 12),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.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
|
||||
return party.some(
|
||||
p =>
|
||||
!p.getHeldItems().some(i => i instanceof SpeciesCritBoosterModifier) &&
|
||||
(checkedSpecies.includes(p.getSpeciesForm(true).speciesId) ||
|
||||
(p.isFusion() && checkedSpecies.includes(p.getFusionSpeciesForm(true).speciesId))),
|
||||
)
|
||||
? 12
|
||||
: 0;
|
||||
},
|
||||
12,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.TOXIC_ORB,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB");
|
||||
|
||||
if (!isHoldingOrb) {
|
||||
const moveset = p
|
||||
.getMoveset(true)
|
||||
.filter(m => !isNullOrUndefined(m))
|
||||
.map(m => m.moveId);
|
||||
const canSetStatus = p.canSetStatus(StatusEffect.TOXIC, true, true, null, true);
|
||||
|
||||
// Moves that take advantage of obtaining the actual status effect
|
||||
const hasStatusMoves = [MoveId.FACADE, MoveId.PSYCHO_SHIFT].some(m => moveset.includes(m));
|
||||
// Moves that take advantage of being able to give the target a status orb
|
||||
// TODO: Take moves (Trick, Fling, Switcheroo) from comment when they are implemented
|
||||
const hasItemMoves = [
|
||||
/* MoveId.TRICK, MoveId.FLING, MoveId.SWITCHEROO */
|
||||
].some(m => moveset.includes(m));
|
||||
|
||||
if (canSetStatus) {
|
||||
// Abilities that take advantage of obtaining the actual status effect, separated based on specificity to the orb
|
||||
const hasGeneralAbility = [
|
||||
AbilityId.QUICK_FEET,
|
||||
AbilityId.GUTS,
|
||||
AbilityId.MARVEL_SCALE,
|
||||
AbilityId.MAGIC_GUARD,
|
||||
].some(a => p.hasAbility(a, false, true));
|
||||
const hasSpecificAbility = [AbilityId.TOXIC_BOOST, AbilityId.POISON_HEAL].some(a =>
|
||||
p.hasAbility(a, false, true),
|
||||
);
|
||||
const hasOppositeAbility = [AbilityId.FLARE_BOOST].some(a => p.hasAbility(a, false, true));
|
||||
|
||||
return hasSpecificAbility || (hasGeneralAbility && !hasOppositeAbility) || hasStatusMoves;
|
||||
}
|
||||
return hasItemMoves;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
},
|
||||
10,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FLAME_ORB,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB");
|
||||
|
||||
if (!isHoldingOrb) {
|
||||
const moveset = p
|
||||
.getMoveset(true)
|
||||
.filter(m => !isNullOrUndefined(m))
|
||||
.map(m => m.moveId);
|
||||
const canSetStatus = p.canSetStatus(StatusEffect.BURN, true, true, null, true);
|
||||
|
||||
// Moves that take advantage of obtaining the actual status effect
|
||||
const hasStatusMoves = [MoveId.FACADE, MoveId.PSYCHO_SHIFT].some(m => moveset.includes(m));
|
||||
// Moves that take advantage of being able to give the target a status orb
|
||||
// TODO: Take moves (Trick, Fling, Switcheroo) from comment when they are implemented
|
||||
const hasItemMoves = [
|
||||
/* MoveId.TRICK, MoveId.FLING, MoveId.SWITCHEROO */
|
||||
].some(m => moveset.includes(m));
|
||||
|
||||
if (canSetStatus) {
|
||||
// Abilities that take advantage of obtaining the actual status effect, separated based on specificity to the orb
|
||||
const hasGeneralAbility = [
|
||||
AbilityId.QUICK_FEET,
|
||||
AbilityId.GUTS,
|
||||
AbilityId.MARVEL_SCALE,
|
||||
AbilityId.MAGIC_GUARD,
|
||||
].some(a => p.hasAbility(a, false, true));
|
||||
const hasSpecificAbility = [AbilityId.FLARE_BOOST].some(a => p.hasAbility(a, false, true));
|
||||
const hasOppositeAbility = [AbilityId.TOXIC_BOOST, AbilityId.POISON_HEAL].some(a =>
|
||||
p.hasAbility(a, false, true),
|
||||
);
|
||||
|
||||
return hasSpecificAbility || (hasGeneralAbility && !hasOppositeAbility) || hasStatusMoves;
|
||||
}
|
||||
return hasItemMoves;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
},
|
||||
10,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MYSTICAL_ROCK,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
let isHoldingMax = false;
|
||||
for (const i of p.getHeldItems()) {
|
||||
if (i.type.id === "MYSTICAL_ROCK") {
|
||||
isHoldingMax = i.getStackCount() === i.getMaxStackCount();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isHoldingMax) {
|
||||
const moveset = p.getMoveset(true).map(m => m.moveId);
|
||||
|
||||
const hasAbility = [
|
||||
AbilityId.DROUGHT,
|
||||
AbilityId.ORICHALCUM_PULSE,
|
||||
AbilityId.DRIZZLE,
|
||||
AbilityId.SAND_STREAM,
|
||||
AbilityId.SAND_SPIT,
|
||||
AbilityId.SNOW_WARNING,
|
||||
AbilityId.ELECTRIC_SURGE,
|
||||
AbilityId.HADRON_ENGINE,
|
||||
AbilityId.PSYCHIC_SURGE,
|
||||
AbilityId.GRASSY_SURGE,
|
||||
AbilityId.SEED_SOWER,
|
||||
AbilityId.MISTY_SURGE,
|
||||
].some(a => p.hasAbility(a, false, true));
|
||||
|
||||
const hasMoves = [
|
||||
MoveId.SUNNY_DAY,
|
||||
MoveId.RAIN_DANCE,
|
||||
MoveId.SANDSTORM,
|
||||
MoveId.SNOWSCAPE,
|
||||
MoveId.HAIL,
|
||||
MoveId.CHILLY_RECEPTION,
|
||||
MoveId.ELECTRIC_TERRAIN,
|
||||
MoveId.PSYCHIC_TERRAIN,
|
||||
MoveId.GRASSY_TERRAIN,
|
||||
MoveId.MISTY_TERRAIN,
|
||||
].some(m => moveset.includes(m));
|
||||
|
||||
return hasAbility || hasMoves;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
},
|
||||
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,
|
||||
() =>
|
||||
!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(ModifierTier.ULTRA);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
function initRogueModifierPool() {
|
||||
modifierPool[ModifierTier.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,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 6,
|
||||
24,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MEGA_BRACELET,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9,
|
||||
36,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.DYNAMAX_BAND,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9,
|
||||
36,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.VOUCHER_PLUS,
|
||||
(_party: Pokemon[], rerollCount: number) =>
|
||||
!globalScene.gameMode.isDaily ? Math.max(3 - rerollCount * 1, 0) : 0,
|
||||
3,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Master modifier pool
|
||||
*/
|
||||
function initMasterModifierPool() {
|
||||
modifierPool[ModifierTier.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,
|
||||
(_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,
|
||||
(party: Pokemon[]) =>
|
||||
!(globalScene.gameMode.isClassic && timedEventManager.areFusionsBoosted()) &&
|
||||
!globalScene.gameMode.isSplicedOnly &&
|
||||
party.filter(p => !p.fusionSpecies).length > 1
|
||||
? 24
|
||||
: 0,
|
||||
24,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MINI_BLACK_HOLE,
|
||||
() =>
|
||||
globalScene.gameMode.isDaily ||
|
||||
(!globalScene.gameMode.isFreshStartChallenge() && globalScene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE))
|
||||
? 1
|
||||
: 0,
|
||||
1,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
function initTrainerModifierPool() {
|
||||
trainerModifierPool[ModifierTier.COMMON] = [
|
||||
new WeightedModifierType(modifierTypes.BERRY, 8),
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
});
|
||||
trainerModifierPool[ModifierTier.GREAT] = [new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3)].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
});
|
||||
trainerModifierPool[ModifierTier.ULTRA] = [
|
||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB, 0),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
});
|
||||
trainerModifierPool[ModifierTier.ROGUE] = [
|
||||
new WeightedModifierType(modifierTypes.FOCUS_BAND, 2),
|
||||
new WeightedModifierType(modifierTypes.LUCKY_EGG, 4),
|
||||
new WeightedModifierType(modifierTypes.QUICK_CLAW, 1),
|
||||
new WeightedModifierType(modifierTypes.GRIP_CLAW, 1),
|
||||
new WeightedModifierType(modifierTypes.WIDE_LENS, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
});
|
||||
trainerModifierPool[ModifierTier.MASTER] = [
|
||||
new WeightedModifierType(modifierTypes.KINGS_ROCK, 1),
|
||||
new WeightedModifierType(modifierTypes.LEFTOVERS, 1),
|
||||
new WeightedModifierType(modifierTypes.SHELL_BELL, 1),
|
||||
new WeightedModifierType(modifierTypes.SCOPE_LENS, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the enemy buff modifier pool
|
||||
*/
|
||||
function initEnemyBuffModifierPool() {
|
||||
enemyBuffModifierPool[ModifierTier.COMMON] = [
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 9),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 9),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_POISON_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_PARALYZE_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_BURN_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 9),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 4),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
});
|
||||
enemyBuffModifierPool[ModifierTier.GREAT] = [
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
});
|
||||
enemyBuffModifierPool[ModifierTier.ULTRA] = [
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_HEAL, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 5),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
});
|
||||
enemyBuffModifierPool[ModifierTier.ROGUE] = [].map((m: WeightedModifierType) => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
});
|
||||
enemyBuffModifierPool[ModifierTier.MASTER] = [].map((m: WeightedModifierType) => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the daily starter modifier pool
|
||||
*/
|
||||
function initDailyStarterModifierPool() {
|
||||
dailyStarterModifierPool[ModifierTier.COMMON] = [
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 1),
|
||||
new WeightedModifierType(modifierTypes.BERRY, 3),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
});
|
||||
dailyStarterModifierPool[ModifierTier.GREAT] = [new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 5)].map(
|
||||
m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
},
|
||||
);
|
||||
dailyStarterModifierPool[ModifierTier.ULTRA] = [
|
||||
new WeightedModifierType(modifierTypes.REVIVER_SEED, 4),
|
||||
new WeightedModifierType(modifierTypes.SOOTHE_BELL, 1),
|
||||
new WeightedModifierType(modifierTypes.SOUL_DEW, 1),
|
||||
new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
});
|
||||
dailyStarterModifierPool[ModifierTier.ROGUE] = [
|
||||
new WeightedModifierType(modifierTypes.GRIP_CLAW, 5),
|
||||
new WeightedModifierType(modifierTypes.BATON, 2),
|
||||
new WeightedModifierType(modifierTypes.FOCUS_BAND, 5),
|
||||
new WeightedModifierType(modifierTypes.QUICK_CLAW, 3),
|
||||
new WeightedModifierType(modifierTypes.KINGS_ROCK, 3),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
});
|
||||
dailyStarterModifierPool[ModifierTier.MASTER] = [
|
||||
new WeightedModifierType(modifierTypes.LEFTOVERS, 1),
|
||||
new WeightedModifierType(modifierTypes.SHELL_BELL, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
export function initModifierPools() {
|
||||
// The modifier pools the player chooses from during modifier selection
|
||||
initCommonModifierPool();
|
||||
initGreatModifierPool();
|
||||
initUltraModifierPool();
|
||||
initRogueModifierPool();
|
||||
initMasterModifierPool();
|
||||
|
||||
// Modifier pools for specific scenarios
|
||||
initWildModifierPool();
|
||||
initTrainerModifierPool();
|
||||
initEnemyBuffModifierPool();
|
||||
initDailyStarterModifierPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param wave - Wave where we should stop showing the modifier
|
||||
* @param defaultWeight - ModifierType default weight
|
||||
* @returns A WeightedModifierTypeWeightFunc
|
||||
*/
|
||||
function skipInClassicAfterWave(wave: number, defaultWeight: number): WeightedModifierTypeWeightFunc {
|
||||
return () => {
|
||||
const gameMode = globalScene.gameMode;
|
||||
const currentWave = globalScene.currentBattle.waveIndex;
|
||||
return gameMode.isClassic && currentWave >= wave ? 0 : defaultWeight;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function skipInLastClassicWaveOrDefault(defaultWeight: number): WeightedModifierTypeWeightFunc {
|
||||
return skipInClassicAfterWave(199, defaultWeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* High order function that returns a WeightedModifierTypeWeightFunc to ensure Lures don't spawn on Classic 199
|
||||
* or if the lure still has over 60% of its duration left
|
||||
* @param maxBattles The max battles the lure type in question lasts. 10 for green, 15 for Super, 30 for Max
|
||||
* @param weight The desired weight for the lure when it does spawn
|
||||
* @returns A WeightedModifierTypeWeightFunc
|
||||
*/
|
||||
function lureWeightFunc(maxBattles: number, weight: number): WeightedModifierTypeWeightFunc {
|
||||
return () => {
|
||||
const lures = globalScene.getModifiers(DoubleBattleChanceBoosterModifier);
|
||||
return !(globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex === 199) &&
|
||||
(lures.length === 0 ||
|
||||
lures.filter(m => m.getMaxBattles() === maxBattles && m.getBattleCount() >= maxBattles * 0.6).length === 0)
|
||||
? weight
|
||||
: 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if the player has max of a given ball type in Classic
|
||||
* @param ballType The {@linkcode PokeballType} being checked
|
||||
* @returns boolean: true if the player has the maximum of a given ball type
|
||||
*/
|
||||
function hasMaximumBalls(ballType: PokeballType): boolean {
|
||||
return globalScene.gameMode.isClassic && globalScene.pokeballCounts[ballType] >= MAX_PER_TYPE_POKEBALLS;
|
||||
}
|
0
src/modifier/init-modifier-types.ts
Normal file
0
src/modifier/init-modifier-types.ts
Normal file
16
src/modifier/modifier-pools.ts
Normal file
16
src/modifier/modifier-pools.ts
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Contains modifier pools for different contexts in the game.
|
||||
* Can be safely imported without worrying about circular dependencies.
|
||||
*/
|
||||
|
||||
import type { ModifierPool } from "#app/@types/modifier-types";
|
||||
|
||||
export const modifierPool: ModifierPool = {};
|
||||
|
||||
export const wildModifierPool: ModifierPool = {};
|
||||
|
||||
export const trainerModifierPool: ModifierPool = {};
|
||||
|
||||
export const enemyBuffModifierPool: ModifierPool = {};
|
||||
|
||||
export const dailyStarterModifierPool: ModifierPool = {};
|
@ -4,7 +4,7 @@ import { tmPoolTiers, tmSpecies } from "#app/data/balance/tms";
|
||||
import { getBerryEffectDescription, getBerryName } from "#app/data/berry";
|
||||
import { allMoves } from "#app/data/data-lists";
|
||||
import { getNatureName, getNatureStatMultiplier } from "#app/data/nature";
|
||||
import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball";
|
||||
import { getPokeballCatchMultiplier, getPokeballName } from "#app/data/pokeball";
|
||||
import { pokemonFormChanges, SpeciesFormChangeCondition } from "#app/data/pokemon-forms";
|
||||
import { SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms/form-change-triggers";
|
||||
import { FormChangeItem } from "#enums/form-change-item";
|
||||
@ -97,9 +97,8 @@ import {
|
||||
CriticalCatchChanceBoosterModifier,
|
||||
FieldEffectModifier,
|
||||
} from "#app/modifier/modifier";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import Overrides from "#app/overrides";
|
||||
import { Unlockables } from "#app/system/unlockables";
|
||||
import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "#app/system/voucher";
|
||||
import type { PokemonMoveSelectFilter, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||
import PartyUiHandler from "#app/ui/party-ui-handler";
|
||||
@ -113,7 +112,6 @@ import {
|
||||
padInt,
|
||||
randSeedInt,
|
||||
} from "#app/utils/common";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
@ -127,18 +125,15 @@ import { StatusEffect } from "#enums/status-effect";
|
||||
import i18next from "i18next";
|
||||
import { timedEventManager } from "#app/global-event-manager";
|
||||
import { TYPE_BOOST_ITEM_BOOST_PERCENT } from "#app/constants";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
|
||||
|
||||
import { getModifierPoolForType } from "#app/utils/modifier-pool-utils";
|
||||
import type { ModifierTypeFunc, WeightedModifierTypeWeightFunc } from "#app/@types/modifier-types";
|
||||
|
||||
const outputModifierData = false;
|
||||
const useMaxWeightForOutput = false;
|
||||
|
||||
export enum ModifierPoolType {
|
||||
PLAYER,
|
||||
WILD,
|
||||
TRAINER,
|
||||
ENEMY_BUFF,
|
||||
DAILY_STARTER,
|
||||
}
|
||||
|
||||
type NewModifierFunc = (type: ModifierType, args: any[]) => Modifier;
|
||||
|
||||
export class ModifierType {
|
||||
@ -299,7 +294,7 @@ export interface GeneratedPersistentModifierType {
|
||||
getPregenArgs(): any[];
|
||||
}
|
||||
|
||||
class AddPokeballModifierType extends ModifierType {
|
||||
export class AddPokeballModifierType extends ModifierType {
|
||||
private pokeballType: PokeballType;
|
||||
private count: number;
|
||||
|
||||
@ -329,7 +324,7 @@ class AddPokeballModifierType extends ModifierType {
|
||||
}
|
||||
}
|
||||
|
||||
class AddVoucherModifierType extends ModifierType {
|
||||
export class AddVoucherModifierType extends ModifierType {
|
||||
private voucherType: VoucherType;
|
||||
private count: number;
|
||||
|
||||
@ -1794,52 +1789,8 @@ export class EnemyEndureChanceModifierType extends ModifierType {
|
||||
}
|
||||
}
|
||||
|
||||
export type ModifierTypeFunc = () => ModifierType;
|
||||
type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: number) => number;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param wave - Wave where we should stop showing the modifier
|
||||
* @param defaultWeight - ModifierType default weight
|
||||
* @returns A WeightedModifierTypeWeightFunc
|
||||
*/
|
||||
function skipInClassicAfterWave(wave: number, defaultWeight: number): WeightedModifierTypeWeightFunc {
|
||||
return () => {
|
||||
const gameMode = globalScene.gameMode;
|
||||
const currentWave = globalScene.currentBattle.waveIndex;
|
||||
return gameMode.isClassic && currentWave >= wave ? 0 : defaultWeight;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function skipInLastClassicWaveOrDefault(defaultWeight: number): WeightedModifierTypeWeightFunc {
|
||||
return skipInClassicAfterWave(199, defaultWeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* High order function that returns a WeightedModifierTypeWeightFunc to ensure Lures don't spawn on Classic 199
|
||||
* or if the lure still has over 60% of its duration left
|
||||
* @param maxBattles The max battles the lure type in question lasts. 10 for green, 15 for Super, 30 for Max
|
||||
* @param weight The desired weight for the lure when it does spawn
|
||||
* @returns A WeightedModifierTypeWeightFunc
|
||||
*/
|
||||
function lureWeightFunc(maxBattles: number, weight: number): WeightedModifierTypeWeightFunc {
|
||||
return () => {
|
||||
const lures = globalScene.getModifiers(DoubleBattleChanceBoosterModifier);
|
||||
return !(globalScene.gameMode.isClassic && globalScene.currentBattle.waveIndex === 199) &&
|
||||
(lures.length === 0 ||
|
||||
lures.filter(m => m.getMaxBattles() === maxBattles && m.getBattleCount() >= maxBattles * 0.6).length === 0)
|
||||
? weight
|
||||
: 0;
|
||||
};
|
||||
}
|
||||
class WeightedModifierType {
|
||||
export class WeightedModifierType {
|
||||
public modifierType: ModifierType;
|
||||
public weight: number | WeightedModifierTypeWeightFunc;
|
||||
public maxWeight: number | WeightedModifierTypeWeightFunc;
|
||||
@ -1860,6 +1811,7 @@ class WeightedModifierType {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type BaseModifierOverride = {
|
||||
name: Exclude<ModifierTypeKeys, GeneratorModifierOverride["name"]>;
|
||||
count?: number;
|
||||
@ -2423,737 +2375,12 @@ export const modifierTypes = {
|
||||
),
|
||||
};
|
||||
|
||||
interface ModifierPool {
|
||||
export interface ModifierPool {
|
||||
[tier: string]: WeightedModifierType[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if the player has max of a given ball type in Classic
|
||||
* @param ballType The {@linkcode PokeballType} being checked
|
||||
* @returns boolean: true if the player has the maximum of a given ball type
|
||||
*/
|
||||
function hasMaximumBalls(ballType: PokeballType): boolean {
|
||||
return globalScene.gameMode.isClassic && globalScene.pokeballCounts[ballType] >= MAX_PER_TYPE_POKEBALLS;
|
||||
}
|
||||
|
||||
const modifierPool: ModifierPool = {
|
||||
[ModifierTier.COMMON]: [
|
||||
new WeightedModifierType(modifierTypes.POKEBALL, () => (hasMaximumBalls(PokeballType.POKEBALL) ? 0 : 6), 6),
|
||||
new WeightedModifierType(modifierTypes.RARE_CANDY, 2),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 10 && p.getHpRatio() <= 0.875 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.SUPER_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 25 && p.getHpRatio() <= 0.75 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.ETHER,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_ETHER,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.LURE, lureWeightFunc(10, 2)),
|
||||
new WeightedModifierType(modifierTypes.TEMP_STAT_STAGE_BOOSTER, 4),
|
||||
new WeightedModifierType(modifierTypes.BERRY, 2),
|
||||
new WeightedModifierType(modifierTypes.TM_COMMON, 2),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.GREAT]: [
|
||||
new WeightedModifierType(modifierTypes.GREAT_BALL, () => (hasMaximumBalls(PokeballType.GREAT_BALL) ? 0 : 6), 6),
|
||||
new WeightedModifierType(modifierTypes.PP_UP, 2),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FULL_HEAL,
|
||||
(party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!!p.status &&
|
||||
!p.getHeldItems().some(i => {
|
||||
if (i instanceof TurnStatusEffectModifier) {
|
||||
return (i as TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return statusEffectPartyMemberCount * 6;
|
||||
},
|
||||
18,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.REVIVE,
|
||||
(party: Pokemon[]) => {
|
||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||
return faintedPartyMemberCount * 9;
|
||||
},
|
||||
27,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_REVIVE,
|
||||
(party: Pokemon[]) => {
|
||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||
return faintedPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.SACRED_ASH,
|
||||
(party: Pokemon[]) => {
|
||||
return party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
||||
},
|
||||
1,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.HYPER_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.625 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_POTION,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.5 && !p.isFainted()).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FULL_RESTORE,
|
||||
(party: Pokemon[]) => {
|
||||
const statusEffectPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!!p.status &&
|
||||
!p.getHeldItems().some(i => {
|
||||
if (i instanceof TurnStatusEffectModifier) {
|
||||
return (i as TurnStatusEffectModifier).getStatusEffect() === p.status?.effect;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
const thresholdPartyMemberCount = Math.floor(
|
||||
(Math.min(party.filter(p => p.getInverseHp() >= 100 && p.getHpRatio() <= 0.5 && !p.isFainted()).length, 3) +
|
||||
statusEffectPartyMemberCount) /
|
||||
2,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.ELIXIR,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
},
|
||||
9,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MAX_ELIXIR,
|
||||
(party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(
|
||||
party.filter(
|
||||
p =>
|
||||
p.hp &&
|
||||
!p.getHeldItems().some(m => m instanceof BerryModifier && m.berryType === BerryType.LEPPA) &&
|
||||
p
|
||||
.getMoveset()
|
||||
.filter(m => m.ppUsed && m.getMovePp() - m.ppUsed <= 5 && m.ppUsed > Math.floor(m.getMovePp() / 2))
|
||||
.length,
|
||||
).length,
|
||||
3,
|
||||
);
|
||||
return thresholdPartyMemberCount;
|
||||
},
|
||||
3,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.DIRE_HIT, 4),
|
||||
new WeightedModifierType(modifierTypes.SUPER_LURE, lureWeightFunc(15, 4)),
|
||||
new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)),
|
||||
new WeightedModifierType(modifierTypes.SPECIES_STAT_BOOSTER, 4),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.EVOLUTION_ITEM,
|
||||
() => {
|
||||
return Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 15), 8);
|
||||
},
|
||||
8,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.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,
|
||||
(party: Pokemon[]) => {
|
||||
if (!party.find(p => p.getLearnableLevelMoves().length)) {
|
||||
return 0;
|
||||
}
|
||||
const highestPartyLevel = party
|
||||
.map(p => p.level)
|
||||
.reduce((highestLevel: number, level: number) => Math.max(highestLevel, level), 1);
|
||||
return Math.min(Math.ceil(highestPartyLevel / 20), 4);
|
||||
},
|
||||
4,
|
||||
),
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3),
|
||||
new WeightedModifierType(modifierTypes.TERA_SHARD, (party: Pokemon[]) =>
|
||||
party.filter(
|
||||
p =>
|
||||
!(p.hasSpecies(SpeciesId.TERAPAGOS) || p.hasSpecies(SpeciesId.OGERPON) || p.hasSpecies(SpeciesId.SHEDINJA)),
|
||||
).length > 0
|
||||
? 1
|
||||
: 0,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.DNA_SPLICERS,
|
||||
(party: Pokemon[]) => {
|
||||
if (party.filter(p => !p.fusionSpecies).length > 1) {
|
||||
if (globalScene.gameMode.isSplicedOnly) {
|
||||
return 4;
|
||||
}
|
||||
if (globalScene.gameMode.isClassic && timedEventManager.areFusionsBoosted()) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
4,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.VOUCHER,
|
||||
(_party: Pokemon[], rerollCount: number) => (!globalScene.gameMode.isDaily ? Math.max(1 - rerollCount, 0) : 0),
|
||||
1,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ULTRA]: [
|
||||
new WeightedModifierType(modifierTypes.ULTRA_BALL, () => (hasMaximumBalls(PokeballType.ULTRA_BALL) ? 0 : 15), 15),
|
||||
new WeightedModifierType(modifierTypes.MAX_LURE, lureWeightFunc(30, 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,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 15) * 4, 32),
|
||||
32,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.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[]) => {
|
||||
const { gameMode, gameData } = globalScene;
|
||||
if (gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) {
|
||||
return party.some(p => {
|
||||
// Check if Pokemon's species (or fusion species, if applicable) can evolve or if they're G-Max'd
|
||||
if (
|
||||
!p.isMax() &&
|
||||
(p.getSpeciesForm(true).speciesId in pokemonEvolutions ||
|
||||
(p.isFusion() && p.getFusionSpeciesForm(true).speciesId in pokemonEvolutions))
|
||||
) {
|
||||
// Check if Pokemon is already holding an Eviolite
|
||||
return !p.getHeldItems().some(i => i.type.id === "EVIOLITE");
|
||||
}
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
}
|
||||
return 0;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.RARE_SPECIES_STAT_BOOSTER, 12),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.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
|
||||
return party.some(
|
||||
p =>
|
||||
!p.getHeldItems().some(i => i instanceof SpeciesCritBoosterModifier) &&
|
||||
(checkedSpecies.includes(p.getSpeciesForm(true).speciesId) ||
|
||||
(p.isFusion() && checkedSpecies.includes(p.getFusionSpeciesForm(true).speciesId))),
|
||||
)
|
||||
? 12
|
||||
: 0;
|
||||
},
|
||||
12,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.TOXIC_ORB,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB");
|
||||
|
||||
if (!isHoldingOrb) {
|
||||
const moveset = p
|
||||
.getMoveset(true)
|
||||
.filter(m => !isNullOrUndefined(m))
|
||||
.map(m => m.moveId);
|
||||
const canSetStatus = p.canSetStatus(StatusEffect.TOXIC, true, true, null, true);
|
||||
|
||||
// Moves that take advantage of obtaining the actual status effect
|
||||
const hasStatusMoves = [MoveId.FACADE, MoveId.PSYCHO_SHIFT].some(m => moveset.includes(m));
|
||||
// Moves that take advantage of being able to give the target a status orb
|
||||
// TODO: Take moves (Trick, Fling, Switcheroo) from comment when they are implemented
|
||||
const hasItemMoves = [
|
||||
/* MoveId.TRICK, MoveId.FLING, MoveId.SWITCHEROO */
|
||||
].some(m => moveset.includes(m));
|
||||
|
||||
if (canSetStatus) {
|
||||
// Abilities that take advantage of obtaining the actual status effect, separated based on specificity to the orb
|
||||
const hasGeneralAbility = [
|
||||
AbilityId.QUICK_FEET,
|
||||
AbilityId.GUTS,
|
||||
AbilityId.MARVEL_SCALE,
|
||||
AbilityId.MAGIC_GUARD,
|
||||
].some(a => p.hasAbility(a, false, true));
|
||||
const hasSpecificAbility = [AbilityId.TOXIC_BOOST, AbilityId.POISON_HEAL].some(a =>
|
||||
p.hasAbility(a, false, true),
|
||||
);
|
||||
const hasOppositeAbility = [AbilityId.FLARE_BOOST].some(a => p.hasAbility(a, false, true));
|
||||
|
||||
return hasSpecificAbility || (hasGeneralAbility && !hasOppositeAbility) || hasStatusMoves;
|
||||
}
|
||||
return hasItemMoves;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
},
|
||||
10,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.FLAME_ORB,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
const isHoldingOrb = p.getHeldItems().some(i => i.type.id === "FLAME_ORB" || i.type.id === "TOXIC_ORB");
|
||||
|
||||
if (!isHoldingOrb) {
|
||||
const moveset = p
|
||||
.getMoveset(true)
|
||||
.filter(m => !isNullOrUndefined(m))
|
||||
.map(m => m.moveId);
|
||||
const canSetStatus = p.canSetStatus(StatusEffect.BURN, true, true, null, true);
|
||||
|
||||
// Moves that take advantage of obtaining the actual status effect
|
||||
const hasStatusMoves = [MoveId.FACADE, MoveId.PSYCHO_SHIFT].some(m => moveset.includes(m));
|
||||
// Moves that take advantage of being able to give the target a status orb
|
||||
// TODO: Take moves (Trick, Fling, Switcheroo) from comment when they are implemented
|
||||
const hasItemMoves = [
|
||||
/* MoveId.TRICK, MoveId.FLING, MoveId.SWITCHEROO */
|
||||
].some(m => moveset.includes(m));
|
||||
|
||||
if (canSetStatus) {
|
||||
// Abilities that take advantage of obtaining the actual status effect, separated based on specificity to the orb
|
||||
const hasGeneralAbility = [
|
||||
AbilityId.QUICK_FEET,
|
||||
AbilityId.GUTS,
|
||||
AbilityId.MARVEL_SCALE,
|
||||
AbilityId.MAGIC_GUARD,
|
||||
].some(a => p.hasAbility(a, false, true));
|
||||
const hasSpecificAbility = [AbilityId.FLARE_BOOST].some(a => p.hasAbility(a, false, true));
|
||||
const hasOppositeAbility = [AbilityId.TOXIC_BOOST, AbilityId.POISON_HEAL].some(a =>
|
||||
p.hasAbility(a, false, true),
|
||||
);
|
||||
|
||||
return hasSpecificAbility || (hasGeneralAbility && !hasOppositeAbility) || hasStatusMoves;
|
||||
}
|
||||
return hasItemMoves;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
},
|
||||
10,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MYSTICAL_ROCK,
|
||||
(party: Pokemon[]) => {
|
||||
return party.some(p => {
|
||||
let isHoldingMax = false;
|
||||
for (const i of p.getHeldItems()) {
|
||||
if (i.type.id === "MYSTICAL_ROCK") {
|
||||
isHoldingMax = i.getStackCount() === i.getMaxStackCount();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isHoldingMax) {
|
||||
const moveset = p.getMoveset(true).map(m => m.moveId);
|
||||
|
||||
const hasAbility = [
|
||||
AbilityId.DROUGHT,
|
||||
AbilityId.ORICHALCUM_PULSE,
|
||||
AbilityId.DRIZZLE,
|
||||
AbilityId.SAND_STREAM,
|
||||
AbilityId.SAND_SPIT,
|
||||
AbilityId.SNOW_WARNING,
|
||||
AbilityId.ELECTRIC_SURGE,
|
||||
AbilityId.HADRON_ENGINE,
|
||||
AbilityId.PSYCHIC_SURGE,
|
||||
AbilityId.GRASSY_SURGE,
|
||||
AbilityId.SEED_SOWER,
|
||||
AbilityId.MISTY_SURGE,
|
||||
].some(a => p.hasAbility(a, false, true));
|
||||
|
||||
const hasMoves = [
|
||||
MoveId.SUNNY_DAY,
|
||||
MoveId.RAIN_DANCE,
|
||||
MoveId.SANDSTORM,
|
||||
MoveId.SNOWSCAPE,
|
||||
MoveId.HAIL,
|
||||
MoveId.CHILLY_RECEPTION,
|
||||
MoveId.ELECTRIC_TERRAIN,
|
||||
MoveId.PSYCHIC_TERRAIN,
|
||||
MoveId.GRASSY_TERRAIN,
|
||||
MoveId.MISTY_TERRAIN,
|
||||
].some(m => moveset.includes(m));
|
||||
|
||||
return hasAbility || hasMoves;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
? 10
|
||||
: 0;
|
||||
},
|
||||
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,
|
||||
() =>
|
||||
!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(ModifierTier.ULTRA);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.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,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 6,
|
||||
24,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MEGA_BRACELET,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9,
|
||||
36,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.DYNAMAX_BAND,
|
||||
() => Math.min(Math.ceil(globalScene.currentBattle.waveIndex / 50), 4) * 9,
|
||||
36,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.VOUCHER_PLUS,
|
||||
(_party: Pokemon[], rerollCount: number) =>
|
||||
!globalScene.gameMode.isDaily ? Math.max(3 - rerollCount * 1, 0) : 0,
|
||||
3,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.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,
|
||||
(_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,
|
||||
(party: Pokemon[]) =>
|
||||
!(globalScene.gameMode.isClassic && timedEventManager.areFusionsBoosted()) &&
|
||||
!globalScene.gameMode.isSplicedOnly &&
|
||||
party.filter(p => !p.fusionSpecies).length > 1
|
||||
? 24
|
||||
: 0,
|
||||
24,
|
||||
),
|
||||
new WeightedModifierType(
|
||||
modifierTypes.MINI_BLACK_HOLE,
|
||||
() =>
|
||||
globalScene.gameMode.isDaily ||
|
||||
(!globalScene.gameMode.isFreshStartChallenge() && globalScene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE))
|
||||
? 1
|
||||
: 0,
|
||||
1,
|
||||
),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
}),
|
||||
};
|
||||
|
||||
const wildModifierPool: ModifierPool = {
|
||||
[ModifierTier.COMMON]: [new WeightedModifierType(modifierTypes.BERRY, 1)].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.GREAT]: [new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 1)].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ULTRA]: [
|
||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB, 0),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ROGUE]: [new WeightedModifierType(modifierTypes.LUCKY_EGG, 4)].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.MASTER]: [new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1)].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
}),
|
||||
};
|
||||
|
||||
const trainerModifierPool: ModifierPool = {
|
||||
[ModifierTier.COMMON]: [
|
||||
new WeightedModifierType(modifierTypes.BERRY, 8),
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.GREAT]: [new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3)].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ULTRA]: [
|
||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
||||
new WeightedModifierType(modifierTypes.WHITE_HERB, 0),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ROGUE]: [
|
||||
new WeightedModifierType(modifierTypes.FOCUS_BAND, 2),
|
||||
new WeightedModifierType(modifierTypes.LUCKY_EGG, 4),
|
||||
new WeightedModifierType(modifierTypes.QUICK_CLAW, 1),
|
||||
new WeightedModifierType(modifierTypes.GRIP_CLAW, 1),
|
||||
new WeightedModifierType(modifierTypes.WIDE_LENS, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.MASTER]: [
|
||||
new WeightedModifierType(modifierTypes.KINGS_ROCK, 1),
|
||||
new WeightedModifierType(modifierTypes.LEFTOVERS, 1),
|
||||
new WeightedModifierType(modifierTypes.SHELL_BELL, 1),
|
||||
new WeightedModifierType(modifierTypes.SCOPE_LENS, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
}),
|
||||
};
|
||||
|
||||
const enemyBuffModifierPool: ModifierPool = {
|
||||
[ModifierTier.COMMON]: [
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 9),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 9),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_POISON_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_PARALYZE_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ATTACK_BURN_CHANCE, 3),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 9),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 4),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.GREAT]: [
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 5),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ULTRA]: [
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_BOOSTER, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_DAMAGE_REDUCTION, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_HEAL, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_STATUS_EFFECT_HEAL_CHANCE, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 10),
|
||||
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 5),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ROGUE]: [].map((m: WeightedModifierType) => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.MASTER]: [].map((m: WeightedModifierType) => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
}),
|
||||
};
|
||||
|
||||
const dailyStarterModifierPool: ModifierPool = {
|
||||
[ModifierTier.COMMON]: [
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 1),
|
||||
new WeightedModifierType(modifierTypes.BERRY, 3),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.COMMON);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.GREAT]: [new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 5)].map(m => {
|
||||
m.setTier(ModifierTier.GREAT);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ULTRA]: [
|
||||
new WeightedModifierType(modifierTypes.REVIVER_SEED, 4),
|
||||
new WeightedModifierType(modifierTypes.SOOTHE_BELL, 1),
|
||||
new WeightedModifierType(modifierTypes.SOUL_DEW, 1),
|
||||
new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ULTRA);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.ROGUE]: [
|
||||
new WeightedModifierType(modifierTypes.GRIP_CLAW, 5),
|
||||
new WeightedModifierType(modifierTypes.BATON, 2),
|
||||
new WeightedModifierType(modifierTypes.FOCUS_BAND, 5),
|
||||
new WeightedModifierType(modifierTypes.QUICK_CLAW, 3),
|
||||
new WeightedModifierType(modifierTypes.KINGS_ROCK, 3),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.ROGUE);
|
||||
return m;
|
||||
}),
|
||||
[ModifierTier.MASTER]: [
|
||||
new WeightedModifierType(modifierTypes.LEFTOVERS, 1),
|
||||
new WeightedModifierType(modifierTypes.SHELL_BELL, 1),
|
||||
].map(m => {
|
||||
m.setTier(ModifierTier.MASTER);
|
||||
return m;
|
||||
}),
|
||||
};
|
||||
|
||||
export function getModifierType(modifierTypeFunc: ModifierTypeFunc): ModifierType {
|
||||
@ -3179,28 +2406,6 @@ let enemyBuffModifierPoolThresholds = {};
|
||||
// biome-ignore lint/correctness/noUnusedVariables: TODO explain why this is marked as OK
|
||||
let enemyBuffIgnoredPoolIndexes = {};
|
||||
|
||||
export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool {
|
||||
let pool: ModifierPool;
|
||||
switch (poolType) {
|
||||
case ModifierPoolType.PLAYER:
|
||||
pool = modifierPool;
|
||||
break;
|
||||
case ModifierPoolType.WILD:
|
||||
pool = wildModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.TRAINER:
|
||||
pool = trainerModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
pool = enemyBuffModifierPool;
|
||||
break;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
pool = dailyStarterModifierPool;
|
||||
break;
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
||||
const tierWeights = [768 / 1024, 195 / 1024, 48 / 1024, 12 / 1024, 1 / 1024];
|
||||
/**
|
||||
* Allows a unit test to check if an item exists in the Modifier Pool. Checks the pool directly, rather than attempting to reroll for the item.
|
||||
|
22
src/modifier/modifier-types.ts
Normal file
22
src/modifier/modifier-types.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
import type { AddPokeballModifierType, AllPokemonLevelIncrementModifierType, EvolutionItemModifierTypeGenerator, ModifierType, ModifierTypeGenerator, PokemonLevelIncrementModifierType } from "./modifier-type";
|
||||
|
||||
interface ModifierTypes {
|
||||
POKEBALL: () => AddPokeballModifierType;
|
||||
GREAT_BALL: () => AddPokeballModifierType;
|
||||
ULTRA_BALL: () => AddPokeballModifierType;
|
||||
ROGUE_BALL: () => AddPokeballModifierType;
|
||||
MASTER_BALL: () => AddPokeballModifierType;
|
||||
|
||||
RARE_CANDY: () => PokemonLevelIncrementModifierType;
|
||||
RARER_CANDY: () => AllPokemonLevelIncrementModifierType;
|
||||
|
||||
EVOLUTION_ITEM: () => EvolutionItemModifierTypeGenerator;
|
||||
RARE_EVOLUTION_ITEM: () => EvolutionItemModifierTypeGenerator;
|
||||
|
||||
FORM_CHANGE_ITEM: () =>
|
||||
|
||||
}
|
@ -46,6 +46,7 @@ import { Color, ShadowColor } from "#enums/color";
|
||||
import { FRIENDSHIP_GAIN_FROM_RARE_CANDY } from "#app/data/balance/starters";
|
||||
import { applyAbAttrs, applyPostItemLostAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { ModifierString } from "#app/@types/modifier-types";
|
||||
|
||||
export type ModifierPredicate = (modifier: Modifier) => boolean;
|
||||
|
||||
@ -159,6 +160,15 @@ export abstract class Modifier {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/** */
|
||||
public is<T extends ModifierString>(modifier: ModifierString): this is ModifierConstructorMap[T] {
|
||||
const targetModifier = ModifierClassMap[modifier];
|
||||
if (!targetModifier) {
|
||||
return false;
|
||||
}
|
||||
return this instanceof targetModifier;
|
||||
}
|
||||
|
||||
match(_modifier: Modifier): boolean {
|
||||
return false;
|
||||
}
|
||||
@ -3842,3 +3852,102 @@ export function overrideHeldItems(pokemon: Pokemon, isPlayer = true): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private map from modifier strings to their constructors.
|
||||
*
|
||||
* @remarks
|
||||
* Used for {@linkcode Modifier.is} to check if a modifier is of a certain type without
|
||||
* requiring modifier types to be imported in every file.
|
||||
*/
|
||||
const ModifierClassMap = Object.freeze({
|
||||
PersistentModifier,
|
||||
ConsumableModifier,
|
||||
AddPokeballModifier,
|
||||
AddVoucherModifier,
|
||||
LapsingPersistentModifier,
|
||||
DoubleBattleChanceBoosterModifier,
|
||||
TempStatStageBoosterModifier,
|
||||
TempCritBoosterModifier,
|
||||
MapModifier,
|
||||
MegaEvolutionAccessModifier,
|
||||
GigantamaxAccessModifier,
|
||||
TerastallizeAccessModifier,
|
||||
PokemonHeldItemModifier,
|
||||
LapsingPokemonHeldItemModifier,
|
||||
BaseStatModifier,
|
||||
EvoTrackerModifier,
|
||||
PokemonBaseStatTotalModifier,
|
||||
PokemonBaseStatFlatModifier,
|
||||
PokemonIncrementingStatModifier,
|
||||
StatBoosterModifier,
|
||||
SpeciesStatBoosterModifier,
|
||||
CritBoosterModifier,
|
||||
SpeciesCritBoosterModifier,
|
||||
AttackTypeBoosterModifier,
|
||||
SurviveDamageModifier,
|
||||
BypassSpeedChanceModifier,
|
||||
FlinchChanceModifier,
|
||||
TurnHealModifier,
|
||||
TurnStatusEffectModifier,
|
||||
HitHealModifier,
|
||||
LevelIncrementBoosterModifier,
|
||||
BerryModifier,
|
||||
PreserveBerryModifier,
|
||||
PokemonInstantReviveModifier,
|
||||
ResetNegativeStatStageModifier,
|
||||
FieldEffectModifier,
|
||||
ConsumablePokemonModifier,
|
||||
TerrastalizeModifier,
|
||||
PokemonHpRestoreModifier,
|
||||
PokemonStatusHealModifier,
|
||||
ConsumablePokemonMoveModifier,
|
||||
PokemonPpRestoreModifier,
|
||||
PokemonAllMovePpRestoreModifier,
|
||||
PokemonPpUpModifier,
|
||||
PokemonNatureChangeModifier,
|
||||
PokemonLevelIncrementModifier,
|
||||
TmModifier,
|
||||
RememberMoveModifier,
|
||||
EvolutionItemModifier,
|
||||
FusePokemonModifier,
|
||||
MultipleParticipantExpBonusModifier,
|
||||
HealingBoosterModifier,
|
||||
ExpBoosterModifier,
|
||||
PokemonExpBoosterModifier,
|
||||
ExpShareModifier,
|
||||
ExpBalanceModifier,
|
||||
PokemonFriendshipBoosterModifier,
|
||||
PokemonNatureWeightModifier,
|
||||
PokemonMoveAccuracyBoosterModifier,
|
||||
PokemonMultiHitModifier,
|
||||
PokemonFormChangeItemModifier,
|
||||
MoneyRewardModifier,
|
||||
DamageMoneyRewardModifier,
|
||||
MoneyInterestModifier,
|
||||
HiddenAbilityRateBoosterModifier,
|
||||
ShinyRateBoosterModifier,
|
||||
CriticalCatchChanceBoosterModifier,
|
||||
LockModifierTiersModifier,
|
||||
HealShopCostModifier,
|
||||
BoostBugSpawnModifier,
|
||||
SwitchEffectTransferModifier,
|
||||
HeldItemTransferModifier,
|
||||
TurnHeldItemTransferModifier,
|
||||
ContactHeldItemTransferChanceModifier,
|
||||
IvScannerModifier,
|
||||
ExtraModifierModifier,
|
||||
TempExtraModifierModifier,
|
||||
EnemyPersistentModifier,
|
||||
EnemyDamageMultiplierModifier,
|
||||
EnemyDamageBoosterModifier,
|
||||
EnemyDamageReducerModifier,
|
||||
EnemyTurnHealModifier,
|
||||
EnemyAttackStatusEffectChanceModifier,
|
||||
EnemyStatusEffectHealChanceModifier,
|
||||
EnemyEndureChanceModifier,
|
||||
EnemyFusionChanceModifier,
|
||||
});
|
||||
|
||||
export type ModifierConstructorMap = typeof ModifierClassMap;
|
@ -1,9 +1,9 @@
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import {
|
||||
regenerateModifierPoolThresholds,
|
||||
ModifierPoolType,
|
||||
getEnemyBuffModifierForWave,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { EnemyPersistentModifier } from "#app/modifier/modifier";
|
||||
import { Phase } from "#app/phase";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
|
@ -15,7 +15,8 @@ import type Pokemon from "#app/field/pokemon";
|
||||
import { FieldPosition } from "#enums/field-position";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { BoostBugSpawnModifier, IvScannerModifier, TurnHeldItemTransferModifier } from "#app/modifier/modifier";
|
||||
import { ModifierPoolType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||
import { regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import Overrides from "#app/overrides";
|
||||
import { BattlePhase } from "#app/phases/battle-phase";
|
||||
import { achvs } from "#app/system/achv";
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { ModifierType, ModifierTypeFunc } from "#app/modifier/modifier-type";
|
||||
import type { ModifierType } from "#app/modifier/modifier-type";
|
||||
import type { ModifierTypeFunc } from "#app/@types/modifier-types";
|
||||
import { getModifierType } from "#app/modifier/modifier-type";
|
||||
import i18next from "i18next";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||
import type { ModifierTypeFunc } from "#app/modifier/modifier-type";
|
||||
import type { ModifierTypeFunc } from "#app/@types/modifier-types";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import i18next from "i18next";
|
||||
import { ModifierRewardPhase } from "./modifier-reward-phase";
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import type { ModifierTier } from "#enums/modifier-tier";
|
||||
import type { ModifierTypeOption, ModifierType } from "#app/modifier/modifier-type";
|
||||
import {
|
||||
regenerateModifierPoolThresholds,
|
||||
@ -11,9 +11,9 @@ import {
|
||||
RememberMoveModifierType,
|
||||
PokemonPpRestoreModifierType,
|
||||
PokemonPpUpModifierType,
|
||||
ModifierPoolType,
|
||||
getPlayerModifierTypeOptions,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import type { Modifier } from "#app/modifier/modifier";
|
||||
import {
|
||||
ExtraModifierModifier,
|
||||
|
@ -8,10 +8,10 @@ import { GameModes } from "#enums/game-modes";
|
||||
import type { Modifier } from "#app/modifier/modifier";
|
||||
import {
|
||||
getDailyRunStarterModifiers,
|
||||
ModifierPoolType,
|
||||
modifierTypes,
|
||||
regenerateModifierPoolThresholds,
|
||||
} from "#app/modifier/modifier-type";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { Phase } from "#app/phase";
|
||||
import type { SessionSaveData } from "#app/system/game-data";
|
||||
import { Unlockables } from "#app/system/unlockables";
|
||||
|
@ -4,7 +4,7 @@ import type Phaser from "phaser";
|
||||
import BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
||||
import InputText from "phaser3-rex-plugins/plugins/inputtext";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { ModifierTier } from "../modifier/modifier-tier";
|
||||
import { ModifierTier } from "../enums/modifier-tier";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
|
||||
export enum TextStyle {
|
||||
|
24
src/utils/modifier-pool-utils.ts
Normal file
24
src/utils/modifier-pool-utils.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import {
|
||||
dailyStarterModifierPool,
|
||||
enemyBuffModifierPool,
|
||||
modifierPool,
|
||||
trainerModifierPool,
|
||||
wildModifierPool,
|
||||
} from "#app/modifier/modifier-pools";
|
||||
import type { ModifierPool } from "#app/@types/modifier-types";
|
||||
|
||||
export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool {
|
||||
switch (poolType) {
|
||||
case ModifierPoolType.PLAYER:
|
||||
return modifierPool;
|
||||
case ModifierPoolType.WILD:
|
||||
return wildModifierPool;
|
||||
case ModifierPoolType.TRAINER:
|
||||
return trainerModifierPool;
|
||||
case ModifierPoolType.ENEMY_BUFF:
|
||||
return enemyBuffModifierPool;
|
||||
case ModifierPoolType.DAILY_STARTER:
|
||||
return dailyStarterModifierPool;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import GameManager from "#test/testUtils/gameManager";
|
||||
|
@ -20,7 +20,7 @@ import { UiMode } from "#enums/ui-mode";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { initSceneWithoutEncounterPhase } from "#test/testUtils/gameManagerUtils";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { ClowningAroundEncounter } from "#app/data/mystery-encounters/encounters/clowning-around-encounter";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
|
@ -17,7 +17,7 @@ import { CIVILIZATION_ENCOUNTER_BIOMES } from "#app/data/mystery-encounters/myst
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import * as Utils from "#app/utils/common";
|
||||
|
||||
const namespace = "mysteryEncounters/globalTradeSystem";
|
||||
|
@ -14,7 +14,7 @@ import { UiMode } from "#enums/ui-mode";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { initSceneWithoutEncounterPhase } from "#test/testUtils/gameManagerUtils";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { MysteriousChallengersEncounter } from "#app/data/mystery-encounters/encounters/mysterious-challengers-encounter";
|
||||
import { TrainerConfig } from "#app/data/trainers/trainer-config";
|
||||
import { TrainerPartyCompoundTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||
|
@ -14,7 +14,7 @@ import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||
import { HealShopCostModifier, HitHealModifier, TurnHealModifier } from "#app/modifier/modifier";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { modifierTypes, type PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
|
@ -19,7 +19,7 @@ import { WeirdDreamEncounter } from "#app/data/mystery-encounters/encounters/wei
|
||||
import * as EncounterTransformationSequence from "#app/data/mystery-encounters/utils/encounter-transformation-sequence";
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
|
||||
const namespace = "mysteryEncounters/weirdDream";
|
||||
const defaultParty = [SpeciesId.MAGBY, SpeciesId.HAUNTER, SpeciesId.ABRA];
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type BattleScene from "#app/battle-scene";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import type { CustomModifierSettings } from "#app/modifier/modifier-type";
|
||||
import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
|
Loading…
Reference in New Issue
Block a user