diff --git a/src/@types/all-reward-type.ts b/src/@types/all-reward-type.ts deleted file mode 100644 index e5fdcf5b625..00000000000 --- a/src/@types/all-reward-type.ts +++ /dev/null @@ -1,121 +0,0 @@ -import type { RewardId } from "#enums/reward-id"; -import type { - AddMoneyReward, - AddPokeballReward, - AddVoucherReward, - AllPokemonFullReviveReward, - AllPokemonLevelIncrementReward, - AttackTypeBoosterRewardGenerator, - BaseStatBoosterRewardGenerator, - BerryRewardGenerator, - EvolutionItemRewardGenerator, - FormChangeItemRewardGenerator, - FusePokemonReward, - LapsingTrainerItemReward, - MintRewardGenerator, - PokemonAllMovePpRestoreReward, - PokemonHpRestoreReward, - PokemonLevelIncrementReward, - PokemonPpRestoreReward, - PokemonPpUpReward, - PokemonReviveReward, - PokemonStatusHealReward, - RememberMoveReward, - SpeciesStatBoosterRewardGenerator, - TempStatStageBoosterRewardGenerator, - TeraTypeRewardGenerator, - TmRewardGenerator, -} from "#items/reward"; - -/** - * The type of the `allRewards` const object. - * @todo Make `allRewards` a const object and replace all references to this with `typeof allRewards` - */ -export type allRewardsType = { - // Pokeball rewards - [RewardId.POKEBALL]: () => AddPokeballReward; - [RewardId.GREAT_BALL]: () => AddPokeballReward; - [RewardId.ULTRA_BALL]: () => AddPokeballReward; - [RewardId.ROGUE_BALL]: () => AddPokeballReward; - [RewardId.MASTER_BALL]: () => AddPokeballReward; - - // Voucher rewards - [RewardId.VOUCHER]: () => AddVoucherReward; - [RewardId.VOUCHER_PLUS]: () => AddVoucherReward; - [RewardId.VOUCHER_PREMIUM]: () => AddVoucherReward; - - // Money rewards - [RewardId.NUGGET]: () => AddMoneyReward; - [RewardId.BIG_NUGGET]: () => AddMoneyReward; - [RewardId.RELIC_GOLD]: () => AddMoneyReward; - - // Party-wide consumables - [RewardId.RARER_CANDY]: () => AllPokemonLevelIncrementReward; - [RewardId.SACRED_ASH]: () => AllPokemonFullReviveReward; - - // Pokemon consumables - [RewardId.RARE_CANDY]: () => PokemonLevelIncrementReward; - - [RewardId.EVOLUTION_ITEM]: () => EvolutionItemRewardGenerator; - [RewardId.RARE_EVOLUTION_ITEM]: () => EvolutionItemRewardGenerator; - - [RewardId.POTION]: () => PokemonHpRestoreReward; - [RewardId.SUPER_POTION]: () => PokemonHpRestoreReward; - [RewardId.HYPER_POTION]: () => PokemonHpRestoreReward; - [RewardId.MAX_POTION]: () => PokemonHpRestoreReward; - [RewardId.FULL_RESTORE]: () => PokemonHpRestoreReward; - - [RewardId.REVIVE]: () => PokemonReviveReward; - [RewardId.MAX_REVIVE]: () => PokemonReviveReward; - - [RewardId.FULL_HEAL]: () => PokemonStatusHealReward; - - [RewardId.ETHER]: () => PokemonPpRestoreReward; - [RewardId.MAX_ETHER]: () => PokemonPpRestoreReward; - - [RewardId.ELIXIR]: () => PokemonAllMovePpRestoreReward; - [RewardId.MAX_ELIXIR]: () => PokemonAllMovePpRestoreReward; - - [RewardId.PP_UP]: () => PokemonPpUpReward; - [RewardId.PP_MAX]: () => PokemonPpUpReward; - - [RewardId.MINT]: () => MintRewardGenerator; - - [RewardId.TERA_SHARD]: () => TeraTypeRewardGenerator; - - [RewardId.TM_COMMON]: () => TmRewardGenerator; - [RewardId.TM_GREAT]: () => TmRewardGenerator; - [RewardId.TM_ULTRA]: () => TmRewardGenerator; - - [RewardId.MEMORY_MUSHROOM]: () => RememberMoveReward; - - [RewardId.DNA_SPLICERS]: () => FusePokemonReward; - - // Form change items - [RewardId.FORM_CHANGE_ITEM]: () => FormChangeItemRewardGenerator; - [RewardId.RARE_FORM_CHANGE_ITEM]: () => FormChangeItemRewardGenerator; - - // Held items - - [RewardId.SPECIES_STAT_BOOSTER]: () => SpeciesStatBoosterRewardGenerator; - [RewardId.RARE_SPECIES_STAT_BOOSTER]: () => SpeciesStatBoosterRewardGenerator; - - [RewardId.BASE_STAT_BOOSTER]: () => BaseStatBoosterRewardGenerator; - - [RewardId.ATTACK_TYPE_BOOSTER]: () => AttackTypeBoosterRewardGenerator; - - [RewardId.BERRY]: () => BerryRewardGenerator; - - // [RewardId.MINI_BLACK_HOLE]: () => HeldItemReward, - - // Trainer items - - [RewardId.LURE]: () => LapsingTrainerItemReward; - [RewardId.SUPER_LURE]: () => LapsingTrainerItemReward; - [RewardId.MAX_LURE]: () => LapsingTrainerItemReward; - - [RewardId.TEMP_STAT_STAGE_BOOSTER]: () => TempStatStageBoosterRewardGenerator; - - [RewardId.DIRE_HIT]: () => LapsingTrainerItemReward; - // [RewardId.GOLDEN_POKEBALL]: () => TrainerItemReward, -}; diff --git a/src/@types/rewards.ts b/src/@types/rewards.ts index 19c400c549a..495586ca873 100644 --- a/src/@types/rewards.ts +++ b/src/@types/rewards.ts @@ -2,34 +2,33 @@ import type { HeldItemId } from "#enums/held-item-id"; import type { RewardId } from "#enums/reward-id"; import type { TrainerItemId } from "#enums/trainer-item-id"; import type { Pokemon } from "#field/pokemon"; +import type { allRewardsType } from "#items/all-rewards"; import type { Reward, RewardGenerator } from "#items/reward"; -import type { allRewardsType } from "#types/all-reward-type"; -export type RewardFunc = () => Reward | RewardGenerator; +export type RewardFunc = Reward | RewardGenerator; + // TODO: Remove party from arguments can be accessed from `globalScene` export type WeightedRewardWeightFunc = (party: Pokemon[], rerollCount?: number) => number; export type RewardPoolId = RewardId | HeldItemId | TrainerItemId; type allRewardsInstanceMap = { - [k in keyof allRewardsType as ReturnType extends RewardGenerator ? k : never]: ReturnType< - allRewardsType[k] - >; + [k in keyof allRewardsType as allRewardsType[k] extends RewardGenerator ? k : never]: allRewardsType[k]; }; -export type RewardGeneratorArgMap = { +type RewardGeneratorArgMap = { [k in keyof allRewardsInstanceMap]: Exclude[0], undefined>; }; -/** Union type containing all `RewardId`s corresponding to valid {@linkcode RewardGenerator}s. */ -export type RewardGeneratorId = keyof allRewardsInstanceMap; +/** Union type containing all {@linkcode RewardId}s corresponding to valid {@linkcode RewardGenerator}s. */ +type RewardGeneratorId = keyof allRewardsInstanceMap; -// TODO: SOrt out which types can and cannot be exported -export type RewardGeneratorSpecs = { +type RewardGeneratorSpecs = { id: T; args: RewardGeneratorArgMap[T]; }; +/** Union type used to specify fixed rewards used in generation. */ export type RewardSpecs = T extends RewardGeneratorId ? T | RewardGeneratorSpecs : T; diff --git a/src/data/data-lists.ts b/src/data/data-lists.ts index 6602d40ab75..25b34e11b49 100644 --- a/src/data/data-lists.ts +++ b/src/data/data-lists.ts @@ -5,7 +5,6 @@ import type { TrainerItemId } from "#enums/trainer-item-id"; import type { HeldItem } from "#items/held-item"; import type { TrainerItem } from "#items/trainer-item"; import type { Move } from "#moves/move"; -import type { allRewardsType } from "#types/all-reward-type"; export const allAbilities: Ability[] = []; export const allMoves: Move[] = []; @@ -13,5 +12,3 @@ export const allSpecies: PokemonSpecies[] = []; export const allHeldItems: Record = {}; export const allTrainerItems: Record = {}; -// TODO: Consider moving into `all-rewards.ts` as a const object - files should not be importing this -export const allRewards: allRewardsType = {}; diff --git a/src/init/init.ts b/src/init/init.ts index 4f6731213da..2b8961562da 100644 --- a/src/init/init.ts +++ b/src/init/init.ts @@ -7,7 +7,6 @@ import { initChallenges } from "#data/challenge"; import { initTrainerTypeDialogue } from "#data/dialogue"; import { initPokemonForms } from "#data/pokemon-forms"; import { initHeldItems } from "#items/all-held-items"; -import { initRewards } from "#items/all-rewards"; import { initTrainerItems } from "#items/all-trainer-items"; import { initHeldItemPools } from "#items/init-held-item-pools"; import { initRewardPools } from "#items/init-reward-pools"; @@ -45,6 +44,5 @@ function initItems() { initHeldItemPools(); initTrainerItems(); initTrainerItemPools(); - initRewards(); initRewardPools(); } diff --git a/src/items/all-rewards.ts b/src/items/all-rewards.ts index 10b3f140977..f082d8aa2ef 100644 --- a/src/items/all-rewards.ts +++ b/src/items/all-rewards.ts @@ -1,9 +1,9 @@ -import { allRewards } from "#data/data-lists"; import { PokeballType } from "#enums/pokeball"; import { RewardId } from "#enums/reward-id"; import { RarityTier } from "#enums/reward-tier"; import { TrainerItemId } from "#enums/trainer-item-id"; import { VoucherType } from "#system/voucher"; +import type { RewardFunc } from "#types/rewards"; import { AddMoneyReward, AddPokeballReward, @@ -32,147 +32,159 @@ import { TmRewardGenerator, } from "./reward"; -export function initRewards() { +// TODO: Move to `reward-utils.ts` and un-exportt +export const allRewards = { // Pokeball rewards - allRewards[RewardId.POKEBALL] = () => new AddPokeballReward("pb", PokeballType.POKEBALL, 5, RewardId.POKEBALL); - allRewards[RewardId.GREAT_BALL] = () => new AddPokeballReward("gb", PokeballType.GREAT_BALL, 5, RewardId.GREAT_BALL); - allRewards[RewardId.ULTRA_BALL] = () => new AddPokeballReward("ub", PokeballType.ULTRA_BALL, 5, RewardId.ULTRA_BALL); - allRewards[RewardId.ROGUE_BALL] = () => new AddPokeballReward("rb", PokeballType.ROGUE_BALL, 5, RewardId.ROGUE_BALL); - allRewards[RewardId.MASTER_BALL] = () => - new AddPokeballReward("mb", PokeballType.MASTER_BALL, 1, RewardId.MASTER_BALL); + [RewardId.POKEBALL]: new AddPokeballReward("pb", PokeballType.POKEBALL, 5, RewardId.POKEBALL), + [RewardId.GREAT_BALL]: new AddPokeballReward("gb", PokeballType.GREAT_BALL, 5, RewardId.GREAT_BALL), + [RewardId.ULTRA_BALL]: new AddPokeballReward("ub", PokeballType.ULTRA_BALL, 5, RewardId.ULTRA_BALL), + [RewardId.ROGUE_BALL]: new AddPokeballReward("rb", PokeballType.ROGUE_BALL, 5, RewardId.ROGUE_BALL), + [RewardId.MASTER_BALL]: new AddPokeballReward("mb", PokeballType.MASTER_BALL, 1, RewardId.MASTER_BALL), // Voucher rewards - allRewards[RewardId.VOUCHER] = () => new AddVoucherReward(VoucherType.REGULAR, 1, RewardId.VOUCHER); - allRewards[RewardId.VOUCHER_PLUS] = () => new AddVoucherReward(VoucherType.PLUS, 1, RewardId.VOUCHER_PLUS); - allRewards[RewardId.VOUCHER_PREMIUM] = () => new AddVoucherReward(VoucherType.PREMIUM, 1, RewardId.VOUCHER_PREMIUM); + [RewardId.VOUCHER]: new AddVoucherReward(VoucherType.REGULAR, 1, RewardId.VOUCHER), + [RewardId.VOUCHER_PLUS]: new AddVoucherReward(VoucherType.PLUS, 1, RewardId.VOUCHER_PLUS), + [RewardId.VOUCHER_PREMIUM]: new AddVoucherReward(VoucherType.PREMIUM, 1, RewardId.VOUCHER_PREMIUM), // Money rewards - allRewards[RewardId.NUGGET] = () => - new AddMoneyReward( - "modifierType:ModifierType.NUGGET", - "nugget", - 1, - "modifierType:ModifierType.MoneyRewardModifierType.extra.small", - RewardId.NUGGET, - ); - allRewards[RewardId.BIG_NUGGET] = () => - new AddMoneyReward( - "modifierType:ModifierType.BIG_NUGGET", - "big_nugget", - 2.5, - "modifierType:ModifierType.MoneyRewardModifierType.extra.moderate", - RewardId.BIG_NUGGET, - ); - allRewards[RewardId.RELIC_GOLD] = () => - new AddMoneyReward( - "modifierType:ModifierType.RELIC_GOLD", - "relic_gold", - 10, - "modifierType:ModifierType.MoneyRewardModifierType.extra.large", - RewardId.RELIC_GOLD, - ); + [RewardId.NUGGET]: new AddMoneyReward( + "modifierType:ModifierType.NUGGET", + "nugget", + 1, + "modifierType:ModifierType.MoneyRewardModifierType.extra.small", + RewardId.NUGGET, + ), + [RewardId.BIG_NUGGET]: new AddMoneyReward( + "modifierType:ModifierType.BIG_NUGGET", + "big_nugget", + 2.5, + "modifierType:ModifierType.MoneyRewardModifierType.extra.moderate", + RewardId.BIG_NUGGET, + ), + [RewardId.RELIC_GOLD]: new AddMoneyReward( + "modifierType:ModifierType.RELIC_GOLD", + "relic_gold", + 10, + "modifierType:ModifierType.MoneyRewardModifierType.extra.large", + RewardId.RELIC_GOLD, + ), // Party-wide consumables - allRewards[RewardId.RARER_CANDY] = () => - new AllPokemonLevelIncrementReward("modifierType:ModifierType.RARER_CANDY", "rarer_candy"); - allRewards[RewardId.SACRED_ASH] = () => - new AllPokemonFullReviveReward("modifierType:ModifierType.SACRED_ASH", "sacred_ash"); + [RewardId.RARER_CANDY]: new AllPokemonLevelIncrementReward("modifierType:ModifierType.RARER_CANDY", "rarer_candy"), + [RewardId.SACRED_ASH]: new AllPokemonFullReviveReward("modifierType:ModifierType.SACRED_ASH", "sacred_ash"), // Pokemon consumables - allRewards[RewardId.RARE_CANDY] = () => - new PokemonLevelIncrementReward("modifierType:ModifierType.RARE_CANDY", "rare_candy"); + [RewardId.RARE_CANDY]: new PokemonLevelIncrementReward("modifierType:ModifierType.RARE_CANDY", "rare_candy"), - allRewards[RewardId.EVOLUTION_ITEM] = () => new EvolutionItemRewardGenerator(false, RewardId.EVOLUTION_ITEM); - allRewards[RewardId.RARE_EVOLUTION_ITEM] = () => new EvolutionItemRewardGenerator(true, RewardId.RARE_EVOLUTION_ITEM); + [RewardId.EVOLUTION_ITEM]: new EvolutionItemRewardGenerator(false, RewardId.EVOLUTION_ITEM), + [RewardId.RARE_EVOLUTION_ITEM]: new EvolutionItemRewardGenerator(true, RewardId.RARE_EVOLUTION_ITEM), - allRewards[RewardId.POTION] = () => - new PokemonHpRestoreReward("modifierType:ModifierType.POTION", "potion", RewardId.POTION, 20, 10); - allRewards[RewardId.SUPER_POTION] = () => - new PokemonHpRestoreReward("modifierType:ModifierType.SUPER_POTION", "super_potion", RewardId.SUPER_POTION, 50, 25); - allRewards[RewardId.HYPER_POTION] = () => - new PokemonHpRestoreReward( - "modifierType:ModifierType.HYPER_POTION", - "hyper_potion", - RewardId.HYPER_POTION, - 200, - 50, - ); - allRewards[RewardId.MAX_POTION] = () => - new PokemonHpRestoreReward("modifierType:ModifierType.MAX_POTION", "max_potion", RewardId.MAX_POTION, 0, 100); - allRewards[RewardId.FULL_RESTORE] = () => - new PokemonHpRestoreReward( - "modifierType:ModifierType.FULL_RESTORE", - "full_restore", - RewardId.FULL_RESTORE, - 0, - 100, - true, - ); + [RewardId.POTION]: new PokemonHpRestoreReward("modifierType:ModifierType.POTION", "potion", RewardId.POTION, 20, 10), + [RewardId.SUPER_POTION]: new PokemonHpRestoreReward( + "modifierType:ModifierType.SUPER_POTION", + "super_potion", + RewardId.SUPER_POTION, + 50, + 25, + ), + [RewardId.HYPER_POTION]: new PokemonHpRestoreReward( + "modifierType:ModifierType.HYPER_POTION", + "hyper_potion", + RewardId.HYPER_POTION, + 200, + 50, + ), + [RewardId.MAX_POTION]: new PokemonHpRestoreReward( + "modifierType:ModifierType.MAX_POTION", + "max_potion", + RewardId.MAX_POTION, + 0, + 100, + ), + [RewardId.FULL_RESTORE]: new PokemonHpRestoreReward( + "modifierType:ModifierType.FULL_RESTORE", + "full_restore", + RewardId.FULL_RESTORE, + 0, + 100, + true, + ), - allRewards[RewardId.REVIVE] = () => - new PokemonReviveReward("modifierType:ModifierType.REVIVE", "revive", RewardId.REVIVE, 50); - allRewards[RewardId.MAX_REVIVE] = () => - new PokemonReviveReward("modifierType:ModifierType.MAX_REVIVE", "max_revive", RewardId.MAX_REVIVE, 100); + [RewardId.REVIVE]: new PokemonReviveReward("modifierType:ModifierType.REVIVE", "revive", RewardId.REVIVE, 50), + [RewardId.MAX_REVIVE]: new PokemonReviveReward( + "modifierType:ModifierType.MAX_REVIVE", + "max_revive", + RewardId.MAX_REVIVE, + 100, + ), - allRewards[RewardId.FULL_HEAL] = () => - new PokemonStatusHealReward("modifierType:ModifierType.FULL_HEAL", "full_heal"); + [RewardId.FULL_HEAL]: new PokemonStatusHealReward("modifierType:ModifierType.FULL_HEAL", "full_heal"), - allRewards[RewardId.ETHER] = () => - new PokemonPpRestoreReward("modifierType:ModifierType.ETHER", "ether", RewardId.ETHER, 10); - allRewards[RewardId.MAX_ETHER] = () => - new PokemonPpRestoreReward("modifierType:ModifierType.MAX_ETHER", "max_ether", RewardId.MAX_ETHER, -1); + [RewardId.ETHER]: new PokemonPpRestoreReward("modifierType:ModifierType.ETHER", "ether", RewardId.ETHER, 10), + [RewardId.MAX_ETHER]: new PokemonPpRestoreReward( + "modifierType:ModifierType.MAX_ETHER", + "max_ether", + RewardId.MAX_ETHER, + -1, + ), - allRewards[RewardId.ELIXIR] = () => - new PokemonAllMovePpRestoreReward("modifierType:ModifierType.ELIXIR", "elixir", RewardId.ELIXIR, 10); - allRewards[RewardId.MAX_ELIXIR] = () => - new PokemonAllMovePpRestoreReward("modifierType:ModifierType.MAX_ELIXIR", "max_elixir", RewardId.MAX_ELIXIR, -1); + [RewardId.ELIXIR]: new PokemonAllMovePpRestoreReward( + "modifierType:ModifierType.ELIXIR", + "elixir", + RewardId.ELIXIR, + 10, + ), + [RewardId.MAX_ELIXIR]: new PokemonAllMovePpRestoreReward( + "modifierType:ModifierType.MAX_ELIXIR", + "max_elixir", + RewardId.MAX_ELIXIR, + -1, + ), - allRewards[RewardId.PP_UP] = () => - new PokemonPpUpReward("modifierType:ModifierType.PP_UP", "pp_up", RewardId.PP_UP, 1); - allRewards[RewardId.PP_MAX] = () => - new PokemonPpUpReward("modifierType:ModifierType.PP_MAX", "pp_max", RewardId.PP_MAX, 3); + [RewardId.PP_UP]: new PokemonPpUpReward("modifierType:ModifierType.PP_UP", "pp_up", RewardId.PP_UP, 1), + [RewardId.PP_MAX]: new PokemonPpUpReward("modifierType:ModifierType.PP_MAX", "pp_max", RewardId.PP_MAX, 3), - allRewards[RewardId.MINT] = () => new MintRewardGenerator(); + [RewardId.MINT]: new MintRewardGenerator(), - allRewards[RewardId.TERA_SHARD] = () => new TeraTypeRewardGenerator(); + [RewardId.TERA_SHARD]: new TeraTypeRewardGenerator(), - allRewards[RewardId.TM_COMMON] = () => new TmRewardGenerator(RarityTier.COMMON); - allRewards[RewardId.TM_GREAT] = () => new TmRewardGenerator(RarityTier.GREAT); - allRewards[RewardId.TM_ULTRA] = () => new TmRewardGenerator(RarityTier.ULTRA); + [RewardId.TM_COMMON]: new TmRewardGenerator(RarityTier.COMMON), + [RewardId.TM_GREAT]: new TmRewardGenerator(RarityTier.GREAT), + [RewardId.TM_ULTRA]: new TmRewardGenerator(RarityTier.ULTRA), - allRewards[RewardId.MEMORY_MUSHROOM] = () => - new RememberMoveReward("modifierType:ModifierType.MEMORY_MUSHROOM", "big_mushroom"); + [RewardId.MEMORY_MUSHROOM]: new RememberMoveReward("modifierType:ModifierType.MEMORY_MUSHROOM", "big_mushroom"), - allRewards[RewardId.DNA_SPLICERS] = () => - new FusePokemonReward("modifierType:ModifierType.DNA_SPLICERS", "dna_splicers"); + [RewardId.DNA_SPLICERS]: new FusePokemonReward("modifierType:ModifierType.DNA_SPLICERS", "dna_splicers"), // Form change items - allRewards[RewardId.FORM_CHANGE_ITEM] = () => new FormChangeItemRewardGenerator(false, RewardId.FORM_CHANGE_ITEM); - allRewards[RewardId.RARE_FORM_CHANGE_ITEM] = () => - new FormChangeItemRewardGenerator(true, RewardId.RARE_FORM_CHANGE_ITEM); + [RewardId.FORM_CHANGE_ITEM]: new FormChangeItemRewardGenerator(false, RewardId.FORM_CHANGE_ITEM), + [RewardId.RARE_FORM_CHANGE_ITEM]: new FormChangeItemRewardGenerator(true, RewardId.RARE_FORM_CHANGE_ITEM), // Held items - allRewards[RewardId.SPECIES_STAT_BOOSTER] = () => new SpeciesStatBoosterRewardGenerator(false); - allRewards[RewardId.RARE_SPECIES_STAT_BOOSTER] = () => new SpeciesStatBoosterRewardGenerator(true); + [RewardId.SPECIES_STAT_BOOSTER]: new SpeciesStatBoosterRewardGenerator(false), + [RewardId.RARE_SPECIES_STAT_BOOSTER]: new SpeciesStatBoosterRewardGenerator(true), - allRewards[RewardId.BASE_STAT_BOOSTER] = () => new BaseStatBoosterRewardGenerator(); + [RewardId.BASE_STAT_BOOSTER]: new BaseStatBoosterRewardGenerator(), - allRewards[RewardId.ATTACK_TYPE_BOOSTER] = () => new AttackTypeBoosterRewardGenerator(); + [RewardId.ATTACK_TYPE_BOOSTER]: new AttackTypeBoosterRewardGenerator(), - allRewards[RewardId.BERRY] = () => new BerryRewardGenerator(); + [RewardId.BERRY]: new BerryRewardGenerator(), - // MINI_BLACK_HOLE] = () => new HeldItemReward(HeldItemId.MINI_BLACK_HOLE), + // [RewardId.MINI_BLACK_HOLE] = new HeldItemReward(HeldItemId.MINI_BLACK_HOLE), // Trainer items - allRewards[RewardId.LURE] = () => new LapsingTrainerItemReward(TrainerItemId.LURE, RewardId.LURE); - allRewards[RewardId.SUPER_LURE] = () => new LapsingTrainerItemReward(TrainerItemId.SUPER_LURE, RewardId.SUPER_LURE); - allRewards[RewardId.MAX_LURE] = () => new LapsingTrainerItemReward(TrainerItemId.MAX_LURE, RewardId.MAX_LURE); + [RewardId.LURE]: new LapsingTrainerItemReward(TrainerItemId.LURE, RewardId.LURE), + [RewardId.SUPER_LURE]: new LapsingTrainerItemReward(TrainerItemId.SUPER_LURE, RewardId.SUPER_LURE), + [RewardId.MAX_LURE]: new LapsingTrainerItemReward(TrainerItemId.MAX_LURE, RewardId.MAX_LURE), - allRewards[RewardId.TEMP_STAT_STAGE_BOOSTER] = () => new TempStatStageBoosterRewardGenerator(); + [RewardId.TEMP_STAT_STAGE_BOOSTER]: new TempStatStageBoosterRewardGenerator(), - allRewards[RewardId.DIRE_HIT] = () => - new LapsingTrainerItemReward(TrainerItemId.DIRE_HIT, RewardId.TEMP_STAT_STAGE_BOOSTER); - // GOLDEN_POKEBALL] = () => new TrainerItemReward(TrainerItemId.GOLDEN_POKEBALL), -} + [RewardId.DIRE_HIT]: new LapsingTrainerItemReward(TrainerItemId.DIRE_HIT, RewardId.TEMP_STAT_STAGE_BOOSTER), + // [RewardId.GOLDEN_POKEBALL]: new TrainerItemReward(TrainerItemId.GOLDEN_POKEBALL), +} as const satisfies { + [k in RewardId]: RewardFunc; +}; + +export type allRewardsType = typeof allRewards; diff --git a/src/items/reward-utils.ts b/src/items/reward-utils.ts index 9a73ec45f2a..691e2bdbab6 100644 --- a/src/items/reward-utils.ts +++ b/src/items/reward-utils.ts @@ -1,15 +1,9 @@ -import { allRewards } from "#data/data-lists"; import type { HeldItemId } from "#enums/held-item-id"; import { getRewardCategory, RewardCategoryId, RewardId } from "#enums/reward-id"; import type { RarityTier } from "#enums/reward-tier"; import type { TrainerItemId } from "#enums/trainer-item-id"; -import type { - RewardFunc, - RewardGeneratorArgMap, - RewardGeneratorId, - RewardGeneratorSpecs, - RewardPoolId, -} from "#types/rewards"; +import { allRewards } from "#items/all-rewards"; +import type { RewardFunc, RewardPoolId, RewardSpecs } from "#types/rewards"; import { heldItemRarities } from "./held-item-default-tiers"; import { HeldItemReward, @@ -38,72 +32,23 @@ export function isRememberMoveReward(reward: Reward): reward is RememberMoveRewa } /** - * Generates a Reward from a given function. - * @param rewardFunc - */ -function generateReward(rewardFunc: () => Reward): Reward | null; -/** - * Generates a Reward from a given function - * @param generator - * @param pregenArgs Can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc. - */ -function generateReward( - generator: () => T, - pregenArgs?: Parameters[0], -): Reward | null; -function generateReward(rewardFunc: RewardFunc, pregenArgs?: any[]): Reward | null { - const reward = rewardFunc(); - return reward instanceof RewardGenerator ? reward.generateReward(pregenArgs) : reward; -} - -/** - * Dynamically generate a {@linkcode RewardOption} from a given ID. - * @param specs - The {@linkcode RewardGeneratorSpecs} used to generate the reward + * Dynamically generate a {@linkcode RewardOption} from a given RewardSpecs. + * @param specs - The {@linkcode RewardSpecs} used to generate the reward * @param cost - The monetary cost of selecting the option; default `0` * @param tierOverride - An optional {@linkcode RarityTier} to override the option's rarity * @param upgradeCount - The number of tier upgrades having occurred; default `0` * @returns The generated {@linkcode RewardOption}, or `null` if no reward could be generated * @todo Remove `null` from signature eventually */ -export function generateRewardOptionFromId( - specs: RewardGeneratorSpecs, - cost?: number, - tierOverride?: RarityTier, - upgradeCount?: number, -): RewardOption | null; -/** - * Dynamically generate a {@linkcode RewardOption} from a given ID. - * @param id - The {@linkcode GeneratorRewardId} to generate a reward for - * @param cost - The monetary cost of selecting the option; default `0` - * @param tierOverride - An optional {@linkcode RarityTier} to override the option's rarity - * @param upgradeCount - The number of tier upgrades having occurred; default `0` - * @param pregenArgs - Optional arguments used to seed the generator. - * @returns The generated {@linkcode RewardOption}, or `null` if no reward could be generated - */ -export function generateRewardOptionFromId( - id: T, - cost?: number, - tierOverride?: RarityTier, - upgradeCount?: number, - pregenArgs?: RewardGeneratorArgMap[T], -): RewardOption | null; -export function generateRewardOptionFromId( - id: Exclude, - cost?: number, - tierOverride?: RarityTier, - upgradeCount?: number, -): RewardOption | null; -export function generateRewardOptionFromId( - id: RewardGeneratorSpecs | RewardPoolId, +export function generateRewardOptionFromId( + specs: RewardSpecs, cost = 0, tierOverride?: RarityTier, upgradeCount = 0, - pregenArgs?: unknown, ): RewardOption | null { - // Destructure specs into objects - if (typeof id === "object") { - ({ id, args: pregenArgs } = id); - } + // Destructure specs into individual parameters + const pregenArgs = typeof specs === "object" ? specs.args : undefined; + const id: RewardPoolId = typeof specs === "object" ? specs.id : specs; if (isHeldItemId(id)) { const reward = new HeldItemReward(id); @@ -117,9 +62,8 @@ export function generateRewardOptionFromId( return new RewardOption(reward, upgradeCount, tier, cost); } - // TODO: This narrows to `any` - const rewardFunc = allRewards[id]; - const reward = generateReward(rewardFunc, pregenArgs); + const rewardFunc = allRewards[id] as RewardFunc; + const reward = rewardFunc instanceof RewardGenerator ? rewardFunc.generateReward(pregenArgs) : rewardFunc; if (reward) { const tier = tierOverride ?? rewardRarities[id]; return new RewardOption(reward, upgradeCount, tier, cost); diff --git a/src/items/reward.ts b/src/items/reward.ts index 4c72955b5b5..a05cbeda51e 100644 --- a/src/items/reward.ts +++ b/src/items/reward.ts @@ -39,7 +39,7 @@ import { getVoucherTypeIcon, getVoucherTypeName, type VoucherType } from "#syste import type { Exact } from "#types/type-helpers"; import type { PokemonMoveSelectFilter, PokemonSelectFilter } from "#ui/party-ui-handler"; import { PartyUiHandler } from "#ui/party-ui-handler"; -import { formatMoney, NumberHolder, padInt, randSeedInt, randSeedItem } from "#utils/common"; +import { formatMoney, NumberHolder, padInt, randSeedInt, randSeedItem, toDmgValue } from "#utils/common"; import { getEnumKeys, getEnumValues } from "#utils/enums"; import i18next from "i18next"; @@ -97,7 +97,6 @@ type MatchExact = T extends object ? Exact : T; export abstract class Reward { // TODO: If all we care about for categorization is the reward's ID's _category_, why not do it there? - // TODO: Make abstract and readonly public id: RewardId; public localeKey: string; public iconImage: string; @@ -466,35 +465,47 @@ export class ChangeTeraTypeReward extends PokemonReward { pokemon.teraType = this.teraType; return true; } -} - -// todo: denest +} // todo: denest // TODO: Consider removing `revive` from the signature of PokemonHealPhase in the wake of this // (was only used for revives) +/** + * Helper function to instantly restore a Pokemon's hp. + * @param pokemon - The {@linkcode Pokemon} being healed + * @param percentToRestore - The percentage of the Pokemon's {@linkcode Stat.HP | maximum HP} to heal + * @param pointsToRestore - A minimum amount of HP points to restore; default `0` + * @param healStatus - Whether to also heal status ailments; default `false` + * @param fainted - Whether to allow reviving fainted Pokemon; default `false`. + * If `true`, will also disable the effect of {@linkcode TrainerItemEffect.HEALING_BOOSTER | Healing Charms}. + * @returns Whether the healing succeeded + */ function restorePokemonHp( pokemon: Pokemon, percentToRestore: number, - pointsToRestore = 0, - healStatus = false, - fainted = false, + { + pointsToRestore = 0, + healStatus = false, + fainted = false, + }: { + pointsToRestore?: number; + healStatus?: boolean; + fainted?: boolean; + } = {}, ): boolean { - if (!pokemon.hp === fainted) { - if (fainted || healStatus) { - pokemon.resetStatus(true, true, false, false); - } - // Apply HealingCharm - let multiplier = 1; - if (!fainted) { - const hpRestoreMultiplier = new NumberHolder(1); - this.applyPlayerItems(TrainerItemEffect.HEALING_BOOSTER, { numberHolder: hpRestoreMultiplier }); - multiplier = hpRestoreMultiplier.value; - } - const restorePoints = Math.floor(pointsToRestore * multiplier); - const restorePercent = Math.floor(percentToRestore * 0.01 * multiplier * pokemon.getMaxHp()); - pokemon.heal(Math.max(restorePercent, restorePoints, 1)); - return true; + if (pokemon.isFainted() !== fainted) { + return false; } - return false; + if (fainted || healStatus) { + pokemon.resetStatus(true, true, false, false); + } + // Apply HealingCharm + const hpRestoreMultiplier = new NumberHolder(1); + if (!fainted) { + this.applyPlayerItems(TrainerItemEffect.HEALING_BOOSTER, { numberHolder: hpRestoreMultiplier }); + } + const restorePoints = toDmgValue(pointsToRestore * hpRestoreMultiplier.value); + const restorePercent = toDmgValue((percentToRestore / 100) * hpRestoreMultiplier.value * pokemon.getMaxHp()); + pokemon.heal(Math.max(restorePercent, restorePoints)); + return true; } export class PokemonHpRestoreReward extends PokemonReward { @@ -1517,23 +1528,3 @@ export class RewardOption { this.cost = Math.min(Math.round(cost), Number.MAX_SAFE_INTEGER); } } - -// TODO: If necessary, add the rest of the modifier types here. -// For now, doing the minimal work until the modifier rework lands. -const RewardConstructorMap = Object.freeze({ - RewardGenerator, -}); - -/** - * Map of of modifier type strings to their constructor type - */ -export type RewardConstructorMap = typeof RewardConstructorMap; - -/** - * Map of modifier type strings to their instance type - */ -export type RewardInstanceMap = { - [K in keyof RewardConstructorMap]: InstanceType; -}; - -export type RewardString = keyof RewardConstructorMap;