mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-11 09:59:28 +02:00
Reward type safety (#6211)
* Added type safety to reward generators * Removed duplicate class member so biome won't yell at meeeeeee * Update all-reward-type.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update all-rewards.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Moved `allRewards` to a const object; general cleanup * Added `noneReward` * Removed `getPregenArgs` * Resolved kev's commnet * Expunged `RewardFunc` --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
parent
acc12318d7
commit
2aca187c66
47
scripts/create-test/boilerplates/reward.ts
Normal file
47
scripts/create-test/boilerplates/reward.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { AbilityId } from "#enums/ability-id";
|
||||||
|
import { MoveId } from "#enums/move-id";
|
||||||
|
import { RewardId } from "#enums/reward-id";
|
||||||
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { BerryHeldItem } from "#items/berry";
|
||||||
|
import { HeldItemReward } from "#items/reward";
|
||||||
|
import { GameManager } from "#test/test-utils/game-manager";
|
||||||
|
import { generateRewardForTest } from "#test/test-utils/reward-test-utils";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("{{description}}", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.ability(AbilityId.BALL_FETCH)
|
||||||
|
.battleStyle("single")
|
||||||
|
.criticalHits(false)
|
||||||
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
|
.startingLevel(100)
|
||||||
|
.enemyLevel(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should do XYZ when applied", async () => {
|
||||||
|
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||||
|
|
||||||
|
const reward = generateRewardForTest(RewardId.BERRY);
|
||||||
|
expect(reward).toBeInstanceOf(HeldItemReward);
|
||||||
|
game.scene.applyReward(reward, []);
|
||||||
|
expect(true).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
@ -2,20 +2,34 @@ import type { HeldItemId } from "#enums/held-item-id";
|
|||||||
import type { RewardId } from "#enums/reward-id";
|
import type { RewardId } from "#enums/reward-id";
|
||||||
import type { TrainerItemId } from "#enums/trainer-item-id";
|
import type { TrainerItemId } from "#enums/trainer-item-id";
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import type { Reward, RewardGenerator } from "#items/reward";
|
import type { allRewardsType } from "#items/all-rewards";
|
||||||
|
import type { RewardGenerator } from "#items/reward";
|
||||||
|
|
||||||
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 WeightedRewardWeightFunc = (party: Pokemon[], rerollCount?: number) => number;
|
||||||
|
|
||||||
export type RewardPoolId = RewardId | HeldItemId | TrainerItemId;
|
export type RewardPoolId = RewardId | HeldItemId | TrainerItemId;
|
||||||
|
|
||||||
export type RewardGeneratorSpecs = {
|
type allRewardGenerators = {
|
||||||
id: RewardId;
|
[k in keyof allRewardsType as allRewardsType[k] extends RewardGenerator ? k : never]: allRewardsType[k];
|
||||||
args: RewardGeneratorArgs;
|
|
||||||
};
|
};
|
||||||
// TODO: fix this with correctly typed args for different RewardIds
|
|
||||||
|
|
||||||
export type RewardSpecs = RewardPoolId | RewardGeneratorSpecs;
|
type RewardGeneratorArgMap = {
|
||||||
|
[k in keyof allRewardGenerators]: Exclude<Parameters<allRewardGenerators[k]["generateReward"]>[0], undefined>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Union type containing all {@linkcode RewardId}s corresponding to valid {@linkcode RewardGenerator}s. */
|
||||||
|
type RewardGeneratorId = keyof allRewardGenerators;
|
||||||
|
|
||||||
|
type RewardGeneratorSpecs<T extends RewardGeneratorId = RewardGeneratorId> = {
|
||||||
|
id: T;
|
||||||
|
args: RewardGeneratorArgMap[T];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Union type used to specify fixed rewards used in generation. */
|
||||||
|
export type RewardSpecs<T extends RewardPoolId = RewardPoolId> = T extends RewardGeneratorId
|
||||||
|
? T | RewardGeneratorSpecs<T>
|
||||||
|
: T;
|
||||||
|
|
||||||
export type RewardPoolEntry = {
|
export type RewardPoolEntry = {
|
||||||
id: RewardPoolId;
|
id: RewardPoolId;
|
||||||
|
@ -69,8 +69,8 @@ import { HeldItemPoolType, RewardPoolType } from "#enums/reward-pool-type";
|
|||||||
import { ShopCursorTarget } from "#enums/shop-cursor-target";
|
import { ShopCursorTarget } from "#enums/shop-cursor-target";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
|
||||||
import { TextStyle } from "#enums/text-style";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||||
import type { TrainerSlot } from "#enums/trainer-slot";
|
import type { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { TrainerVariant } from "#enums/trainer-variant";
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
@ -86,7 +86,7 @@ import { applyHeldItems } from "#items/all-held-items";
|
|||||||
import { type ApplyTrainerItemsParams, applyTrainerItems } from "#items/apply-trainer-items";
|
import { type ApplyTrainerItemsParams, applyTrainerItems } from "#items/apply-trainer-items";
|
||||||
import type { HeldItemConfiguration } from "#items/held-item-data-types";
|
import type { HeldItemConfiguration } from "#items/held-item-data-types";
|
||||||
import { assignEnemyHeldItemsForWave, assignItemsFromConfiguration } from "#items/held-item-pool";
|
import { assignEnemyHeldItemsForWave, assignItemsFromConfiguration } from "#items/held-item-pool";
|
||||||
import type { Reward } from "#items/reward";
|
import type { MatchExact, Reward } from "#items/reward";
|
||||||
import { getRewardPoolForType } from "#items/reward-pool-utils";
|
import { getRewardPoolForType } from "#items/reward-pool-utils";
|
||||||
import { type EnemyAttackStatusEffectChanceTrainerItem, TrainerItemEffect } from "#items/trainer-item";
|
import { type EnemyAttackStatusEffectChanceTrainerItem, TrainerItemEffect } from "#items/trainer-item";
|
||||||
import {
|
import {
|
||||||
@ -2636,7 +2636,11 @@ export class BattleScene extends SceneBase {
|
|||||||
applyTrainerItems(effect, this.trainerItems, params);
|
applyTrainerItems(effect, this.trainerItems, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyReward<T extends Reward>(reward: T, params: Parameters<T["apply"]>[0], playSound?: boolean): boolean {
|
applyReward<T extends Reward>(
|
||||||
|
reward: T,
|
||||||
|
params: MatchExact<Parameters<T["apply"]>[0]>,
|
||||||
|
playSound?: boolean,
|
||||||
|
): boolean {
|
||||||
const soundName = reward.soundName;
|
const soundName = reward.soundName;
|
||||||
|
|
||||||
if (playSound && !this.sound.get(soundName)) {
|
if (playSound && !this.sound.get(soundName)) {
|
||||||
@ -2780,7 +2784,6 @@ export class BattleScene extends SceneBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO @Wlowscha: Fix this
|
// TODO @Wlowscha: Fix this
|
||||||
/**
|
/**
|
||||||
* Attempt to discard one or more copies of a held item.
|
* Attempt to discard one or more copies of a held item.
|
||||||
@ -2799,23 +2802,6 @@ export class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
return this.removeModifier(itemModifier);
|
return this.removeModifier(itemModifier);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Attempt to discard one or more copies of a held item.
|
|
||||||
* @param itemModifier - The {@linkcode PokemonHeldItemModifier} being discarded
|
|
||||||
* @param discardQuantity - The number of copies to remove (up to the amount currently held); default `1`
|
|
||||||
* @returns Whether the item was successfully discarded.
|
|
||||||
* Removing fewer items than requested is still considered a success.
|
|
||||||
*/
|
|
||||||
tryDiscardHeldItemModifier(itemModifier: PokemonHeldItemModifier, discardQuantity = 1): boolean {
|
|
||||||
const countTaken = Math.min(discardQuantity, itemModifier.stackCount);
|
|
||||||
itemModifier.stackCount -= countTaken;
|
|
||||||
|
|
||||||
if (itemModifier.stackCount > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.removeModifier(itemModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
canTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferQuantity = 1): boolean {
|
canTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferQuantity = 1): boolean {
|
||||||
const mod = itemModifier.clone() as PokemonHeldItemModifier;
|
const mod = itemModifier.clone() as PokemonHeldItemModifier;
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import type { Ability } from "#abilities/ability";
|
import type { Ability } from "#abilities/ability";
|
||||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
import type { HeldItemId } from "#enums/held-item-id";
|
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 { TrainerItemId } from "#enums/trainer-item-id";
|
||||||
import type { HeldItem } from "#items/held-item";
|
import type { HeldItem } from "#items/held-item";
|
||||||
import type { TrainerItem } from "#items/trainer-item";
|
import type { TrainerItem } from "#items/trainer-item";
|
||||||
import type { Move } from "#moves/move";
|
import type { Move } from "#moves/move";
|
||||||
import type { RewardFunc } from "#types/rewards";
|
|
||||||
|
|
||||||
export const allAbilities: Ability[] = [];
|
export const allAbilities: Ability[] = [];
|
||||||
export const allMoves: Move[] = [];
|
export const allMoves: Move[] = [];
|
||||||
@ -14,4 +12,3 @@ export const allSpecies: PokemonSpecies[] = [];
|
|||||||
|
|
||||||
export const allHeldItems: Record<HeldItemId, HeldItem> = {};
|
export const allHeldItems: Record<HeldItemId, HeldItem> = {};
|
||||||
export const allTrainerItems: Record<TrainerItemId, TrainerItem> = {};
|
export const allTrainerItems: Record<TrainerItemId, TrainerItem> = {};
|
||||||
export const allRewards: Record<RewardId, RewardFunc> = {};
|
|
||||||
|
@ -3,13 +3,12 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { pokemonEvolutions, pokemonPrevolutions } from "#balance/pokemon-evolutions";
|
import { pokemonEvolutions, pokemonPrevolutions } from "#balance/pokemon-evolutions";
|
||||||
import { signatureSpecies } from "#balance/signature-species";
|
import { signatureSpecies } from "#balance/signature-species";
|
||||||
import { tmSpecies } from "#balance/tms";
|
import { tmSpecies } from "#balance/tms";
|
||||||
import { allRewards } from "#data/data-lists";
|
|
||||||
import { doubleBattleDialogue } from "#data/double-battle-dialogue";
|
import { doubleBattleDialogue } from "#data/double-battle-dialogue";
|
||||||
import { Gender } from "#data/gender";
|
import { Gender } from "#data/gender";
|
||||||
import type { PokemonSpecies, PokemonSpeciesFilter } from "#data/pokemon-species";
|
import type { PokemonSpecies, PokemonSpeciesFilter } from "#data/pokemon-species";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import type { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
@ -19,6 +18,8 @@ import { TrainerSlot } from "#enums/trainer-slot";
|
|||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { TrainerVariant } from "#enums/trainer-variant";
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
import type { EnemyPokemon } from "#field/pokemon";
|
import type { EnemyPokemon } from "#field/pokemon";
|
||||||
|
import { allRewards } from "#items/all-rewards";
|
||||||
|
import type { Reward, RewardGenerator } from "#items/reward";
|
||||||
import { PokemonMove } from "#moves/pokemon-move";
|
import { PokemonMove } from "#moves/pokemon-move";
|
||||||
import { getIsInitialized, initI18n } from "#plugins/i18n";
|
import { getIsInitialized, initI18n } from "#plugins/i18n";
|
||||||
import type { EvilTeam } from "#trainers/evil-admin-trainer-pools";
|
import type { EvilTeam } from "#trainers/evil-admin-trainer-pools";
|
||||||
@ -28,10 +29,9 @@ import {
|
|||||||
getGymLeaderPartyTemplate,
|
getGymLeaderPartyTemplate,
|
||||||
getWavePartyTemplate,
|
getWavePartyTemplate,
|
||||||
TrainerPartyCompoundTemplate,
|
TrainerPartyCompoundTemplate,
|
||||||
TrainerPartyTemplate,
|
type TrainerPartyTemplate,
|
||||||
trainerPartyTemplates,
|
trainerPartyTemplates,
|
||||||
} from "#trainers/trainer-party-template";
|
} from "#trainers/trainer-party-template";
|
||||||
import type { RewardFunc } from "#types/rewards";
|
|
||||||
import type {
|
import type {
|
||||||
GenAIFunc,
|
GenAIFunc,
|
||||||
GenTrainerItemsFunc,
|
GenTrainerItemsFunc,
|
||||||
@ -109,7 +109,7 @@ export class TrainerConfig {
|
|||||||
public victoryBgm: string;
|
public victoryBgm: string;
|
||||||
public genTrainerItemsFunc: GenTrainerItemsFunc;
|
public genTrainerItemsFunc: GenTrainerItemsFunc;
|
||||||
public genAIFuncs: GenAIFunc[] = [];
|
public genAIFuncs: GenAIFunc[] = [];
|
||||||
public rewardFuncs: RewardFunc[] = [];
|
public rewardFuncs: (Reward | RewardGenerator)[] = [];
|
||||||
public partyTemplates: TrainerPartyTemplate[];
|
public partyTemplates: TrainerPartyTemplate[];
|
||||||
public partyTemplateFunc: PartyTemplateFunc;
|
public partyTemplateFunc: PartyTemplateFunc;
|
||||||
public partyMemberFuncs: PartyMemberFuncs = {};
|
public partyMemberFuncs: PartyMemberFuncs = {};
|
||||||
@ -501,7 +501,7 @@ export class TrainerConfig {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setRewardFuncs(...rewardFuncs: (() => RewardFunc)[]): TrainerConfig {
|
setRewardFuncs(...rewardFuncs: (Reward | RewardGenerator)[]): TrainerConfig {
|
||||||
this.rewardFuncs = rewardFuncs.map(func => () => {
|
this.rewardFuncs = rewardFuncs.map(func => () => {
|
||||||
const rewardFunc = func();
|
const rewardFunc = func();
|
||||||
const reward = rewardFunc();
|
const reward = rewardFunc();
|
||||||
|
@ -52,19 +52,17 @@ export const RewardId = {
|
|||||||
MEMORY_MUSHROOM: 0x2B03,
|
MEMORY_MUSHROOM: 0x2B03,
|
||||||
DNA_SPLICERS: 0x2B04,
|
DNA_SPLICERS: 0x2B04,
|
||||||
|
|
||||||
HELD_ITEM: 0x2C01,
|
SPECIES_STAT_BOOSTER: 0x2C01,
|
||||||
SPECIES_STAT_BOOSTER: 0x2C02,
|
RARE_SPECIES_STAT_BOOSTER: 0x2C02,
|
||||||
RARE_SPECIES_STAT_BOOSTER: 0x2C03,
|
BASE_STAT_BOOSTER: 0x2C03,
|
||||||
BASE_STAT_BOOSTER: 0x2C04,
|
ATTACK_TYPE_BOOSTER: 0x2C04,
|
||||||
ATTACK_TYPE_BOOSTER: 0x2C05,
|
BERRY: 0x2C05,
|
||||||
BERRY: 0x2C06,
|
|
||||||
|
|
||||||
TRAINER_ITEM: 0x2D01,
|
TEMP_STAT_STAGE_BOOSTER: 0x2D01,
|
||||||
TEMP_STAT_STAGE_BOOSTER: 0x2D02,
|
DIRE_HIT: 0x2D02,
|
||||||
DIRE_HIT: 0x2D03,
|
LURE: 0x2D03,
|
||||||
LURE: 0x2D04,
|
SUPER_LURE: 0x2D04,
|
||||||
SUPER_LURE: 0x2D05,
|
MAX_LURE: 0x2D05,
|
||||||
MAX_LURE: 0x2D06,
|
|
||||||
|
|
||||||
FORM_CHANGE_ITEM: 0x2E01,
|
FORM_CHANGE_ITEM: 0x2E01,
|
||||||
RARE_FORM_CHANGE_ITEM: 0x2E02,
|
RARE_FORM_CHANGE_ITEM: 0x2E02,
|
||||||
|
@ -7,7 +7,6 @@ import { initChallenges } from "#data/challenge";
|
|||||||
import { initTrainerTypeDialogue } from "#data/dialogue";
|
import { initTrainerTypeDialogue } from "#data/dialogue";
|
||||||
import { initPokemonForms } from "#data/pokemon-forms";
|
import { initPokemonForms } from "#data/pokemon-forms";
|
||||||
import { initHeldItems } from "#items/all-held-items";
|
import { initHeldItems } from "#items/all-held-items";
|
||||||
import { initRewards } from "#items/all-rewards";
|
|
||||||
import { initTrainerItems } from "#items/all-trainer-items";
|
import { initTrainerItems } from "#items/all-trainer-items";
|
||||||
import { initHeldItemPools } from "#items/init-held-item-pools";
|
import { initHeldItemPools } from "#items/init-held-item-pools";
|
||||||
import { initRewardPools } from "#items/init-reward-pools";
|
import { initRewardPools } from "#items/init-reward-pools";
|
||||||
@ -45,6 +44,5 @@ function initItems() {
|
|||||||
initHeldItemPools();
|
initHeldItemPools();
|
||||||
initTrainerItems();
|
initTrainerItems();
|
||||||
initTrainerItemPools();
|
initTrainerItemPools();
|
||||||
initRewards();
|
|
||||||
initRewardPools();
|
initRewardPools();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { allRewards } from "#data/data-lists";
|
|
||||||
import { PokeballType } from "#enums/pokeball";
|
import { PokeballType } from "#enums/pokeball";
|
||||||
import { RewardId } from "#enums/reward-id";
|
import { RewardId } from "#enums/reward-id";
|
||||||
import { RarityTier } from "#enums/reward-tier";
|
import { RarityTier } from "#enums/reward-tier";
|
||||||
@ -18,6 +17,7 @@ import {
|
|||||||
FusePokemonReward,
|
FusePokemonReward,
|
||||||
LapsingTrainerItemReward,
|
LapsingTrainerItemReward,
|
||||||
MintRewardGenerator,
|
MintRewardGenerator,
|
||||||
|
NoneReward,
|
||||||
PokemonAllMovePpRestoreReward,
|
PokemonAllMovePpRestoreReward,
|
||||||
PokemonHpRestoreReward,
|
PokemonHpRestoreReward,
|
||||||
PokemonLevelIncrementReward,
|
PokemonLevelIncrementReward,
|
||||||
@ -26,157 +26,166 @@ import {
|
|||||||
PokemonReviveReward,
|
PokemonReviveReward,
|
||||||
PokemonStatusHealReward,
|
PokemonStatusHealReward,
|
||||||
RememberMoveReward,
|
RememberMoveReward,
|
||||||
|
type Reward,
|
||||||
|
type RewardGenerator,
|
||||||
SpeciesStatBoosterRewardGenerator,
|
SpeciesStatBoosterRewardGenerator,
|
||||||
TempStatStageBoosterRewardGenerator,
|
TempStatStageBoosterRewardGenerator,
|
||||||
TeraTypeRewardGenerator,
|
TeraTypeRewardGenerator,
|
||||||
TmRewardGenerator,
|
TmRewardGenerator,
|
||||||
} from "./reward";
|
} from "./reward";
|
||||||
|
|
||||||
export function initRewards() {
|
// TODO: Move to `reward-utils.ts` and un-exportt
|
||||||
|
export const allRewards = {
|
||||||
|
[RewardId.NONE]: new NoneReward(),
|
||||||
|
|
||||||
// Pokeball rewards
|
// Pokeball rewards
|
||||||
allRewards[RewardId.POKEBALL] = () => new AddPokeballReward("pb", PokeballType.POKEBALL, 5, RewardId.POKEBALL);
|
[RewardId.POKEBALL]: new AddPokeballReward("pb", PokeballType.POKEBALL, 5, RewardId.POKEBALL),
|
||||||
allRewards[RewardId.GREAT_BALL] = () => new AddPokeballReward("gb", PokeballType.GREAT_BALL, 5, RewardId.GREAT_BALL);
|
[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);
|
[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);
|
[RewardId.ROGUE_BALL]: new AddPokeballReward("rb", PokeballType.ROGUE_BALL, 5, RewardId.ROGUE_BALL),
|
||||||
allRewards[RewardId.MASTER_BALL] = () =>
|
[RewardId.MASTER_BALL]: new AddPokeballReward("mb", PokeballType.MASTER_BALL, 1, RewardId.MASTER_BALL),
|
||||||
new AddPokeballReward("mb", PokeballType.MASTER_BALL, 1, RewardId.MASTER_BALL);
|
|
||||||
|
|
||||||
// Voucher rewards
|
// Voucher rewards
|
||||||
allRewards[RewardId.VOUCHER] = () => new AddVoucherReward(VoucherType.REGULAR, 1, RewardId.VOUCHER);
|
[RewardId.VOUCHER]: new AddVoucherReward(VoucherType.REGULAR, 1, RewardId.VOUCHER),
|
||||||
allRewards[RewardId.VOUCHER_PLUS] = () => new AddVoucherReward(VoucherType.PLUS, 1, RewardId.VOUCHER_PLUS);
|
[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_PREMIUM]: new AddVoucherReward(VoucherType.PREMIUM, 1, RewardId.VOUCHER_PREMIUM),
|
||||||
|
|
||||||
// Money rewards
|
// Money rewards
|
||||||
allRewards[RewardId.NUGGET] = () =>
|
[RewardId.NUGGET]: new AddMoneyReward(
|
||||||
new AddMoneyReward(
|
|
||||||
"modifierType:ModifierType.NUGGET",
|
"modifierType:ModifierType.NUGGET",
|
||||||
"nugget",
|
"nugget",
|
||||||
1,
|
1,
|
||||||
"modifierType:ModifierType.MoneyRewardModifierType.extra.small",
|
"modifierType:ModifierType.MoneyRewardModifierType.extra.small",
|
||||||
RewardId.NUGGET,
|
RewardId.NUGGET,
|
||||||
);
|
),
|
||||||
allRewards[RewardId.BIG_NUGGET] = () =>
|
[RewardId.BIG_NUGGET]: new AddMoneyReward(
|
||||||
new AddMoneyReward(
|
|
||||||
"modifierType:ModifierType.BIG_NUGGET",
|
"modifierType:ModifierType.BIG_NUGGET",
|
||||||
"big_nugget",
|
"big_nugget",
|
||||||
2.5,
|
2.5,
|
||||||
"modifierType:ModifierType.MoneyRewardModifierType.extra.moderate",
|
"modifierType:ModifierType.MoneyRewardModifierType.extra.moderate",
|
||||||
RewardId.BIG_NUGGET,
|
RewardId.BIG_NUGGET,
|
||||||
);
|
),
|
||||||
allRewards[RewardId.RELIC_GOLD] = () =>
|
[RewardId.RELIC_GOLD]: new AddMoneyReward(
|
||||||
new AddMoneyReward(
|
|
||||||
"modifierType:ModifierType.RELIC_GOLD",
|
"modifierType:ModifierType.RELIC_GOLD",
|
||||||
"relic_gold",
|
"relic_gold",
|
||||||
10,
|
10,
|
||||||
"modifierType:ModifierType.MoneyRewardModifierType.extra.large",
|
"modifierType:ModifierType.MoneyRewardModifierType.extra.large",
|
||||||
RewardId.RELIC_GOLD,
|
RewardId.RELIC_GOLD,
|
||||||
);
|
),
|
||||||
|
|
||||||
// Party-wide consumables
|
// Party-wide consumables
|
||||||
allRewards[RewardId.RARER_CANDY] = () =>
|
[RewardId.RARER_CANDY]: new AllPokemonLevelIncrementReward("modifierType:ModifierType.RARER_CANDY", "rarer_candy"),
|
||||||
new AllPokemonLevelIncrementReward("modifierType:ModifierType.RARER_CANDY", "rarer_candy");
|
[RewardId.SACRED_ASH]: new AllPokemonFullReviveReward("modifierType:ModifierType.SACRED_ASH", "sacred_ash"),
|
||||||
allRewards[RewardId.SACRED_ASH] = () =>
|
|
||||||
new AllPokemonFullReviveReward("modifierType:ModifierType.SACRED_ASH", "sacred_ash");
|
|
||||||
|
|
||||||
// Pokemon consumables
|
// Pokemon consumables
|
||||||
allRewards[RewardId.RARE_CANDY] = () =>
|
[RewardId.RARE_CANDY]: new PokemonLevelIncrementReward("modifierType:ModifierType.RARE_CANDY", "rare_candy"),
|
||||||
new PokemonLevelIncrementReward("modifierType:ModifierType.RARE_CANDY", "rare_candy");
|
|
||||||
|
|
||||||
allRewards[RewardId.EVOLUTION_ITEM] = () => new EvolutionItemRewardGenerator(false, RewardId.EVOLUTION_ITEM);
|
[RewardId.EVOLUTION_ITEM]: new EvolutionItemRewardGenerator(false, RewardId.EVOLUTION_ITEM),
|
||||||
allRewards[RewardId.RARE_EVOLUTION_ITEM] = () => new EvolutionItemRewardGenerator(true, RewardId.RARE_EVOLUTION_ITEM);
|
[RewardId.RARE_EVOLUTION_ITEM]: new EvolutionItemRewardGenerator(true, RewardId.RARE_EVOLUTION_ITEM),
|
||||||
|
|
||||||
allRewards[RewardId.POTION] = () =>
|
[RewardId.POTION]: new PokemonHpRestoreReward("modifierType:ModifierType.POTION", "potion", RewardId.POTION, 20, 10),
|
||||||
new PokemonHpRestoreReward("modifierType:ModifierType.POTION", "potion", RewardId.POTION, 20, 10);
|
[RewardId.SUPER_POTION]: new PokemonHpRestoreReward(
|
||||||
allRewards[RewardId.SUPER_POTION] = () =>
|
"modifierType:ModifierType.SUPER_POTION",
|
||||||
new PokemonHpRestoreReward("modifierType:ModifierType.SUPER_POTION", "super_potion", RewardId.SUPER_POTION, 50, 25);
|
"super_potion",
|
||||||
allRewards[RewardId.HYPER_POTION] = () =>
|
RewardId.SUPER_POTION,
|
||||||
new PokemonHpRestoreReward(
|
50,
|
||||||
|
25,
|
||||||
|
),
|
||||||
|
[RewardId.HYPER_POTION]: new PokemonHpRestoreReward(
|
||||||
"modifierType:ModifierType.HYPER_POTION",
|
"modifierType:ModifierType.HYPER_POTION",
|
||||||
"hyper_potion",
|
"hyper_potion",
|
||||||
RewardId.HYPER_POTION,
|
RewardId.HYPER_POTION,
|
||||||
200,
|
200,
|
||||||
50,
|
50,
|
||||||
);
|
),
|
||||||
allRewards[RewardId.MAX_POTION] = () =>
|
[RewardId.MAX_POTION]: new PokemonHpRestoreReward(
|
||||||
new PokemonHpRestoreReward("modifierType:ModifierType.MAX_POTION", "max_potion", RewardId.MAX_POTION, 0, 100);
|
"modifierType:ModifierType.MAX_POTION",
|
||||||
allRewards[RewardId.FULL_RESTORE] = () =>
|
"max_potion",
|
||||||
new PokemonHpRestoreReward(
|
RewardId.MAX_POTION,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
),
|
||||||
|
[RewardId.FULL_RESTORE]: new PokemonHpRestoreReward(
|
||||||
"modifierType:ModifierType.FULL_RESTORE",
|
"modifierType:ModifierType.FULL_RESTORE",
|
||||||
"full_restore",
|
"full_restore",
|
||||||
RewardId.FULL_RESTORE,
|
RewardId.FULL_RESTORE,
|
||||||
0,
|
0,
|
||||||
100,
|
100,
|
||||||
true,
|
true,
|
||||||
);
|
),
|
||||||
|
|
||||||
allRewards[RewardId.REVIVE] = () =>
|
[RewardId.REVIVE]: new PokemonReviveReward("modifierType:ModifierType.REVIVE", "revive", RewardId.REVIVE, 50),
|
||||||
new PokemonReviveReward("modifierType:ModifierType.REVIVE", "revive", RewardId.REVIVE, 50);
|
[RewardId.MAX_REVIVE]: new PokemonReviveReward(
|
||||||
allRewards[RewardId.MAX_REVIVE] = () =>
|
"modifierType:ModifierType.MAX_REVIVE",
|
||||||
new PokemonReviveReward("modifierType:ModifierType.MAX_REVIVE", "max_revive", RewardId.MAX_REVIVE, 100);
|
"max_revive",
|
||||||
|
RewardId.MAX_REVIVE,
|
||||||
|
100,
|
||||||
|
),
|
||||||
|
|
||||||
allRewards[RewardId.FULL_HEAL] = () =>
|
[RewardId.FULL_HEAL]: new PokemonStatusHealReward("modifierType:ModifierType.FULL_HEAL", "full_heal"),
|
||||||
new PokemonStatusHealReward("modifierType:ModifierType.FULL_HEAL", "full_heal");
|
|
||||||
|
|
||||||
allRewards[RewardId.ETHER] = () =>
|
[RewardId.ETHER]: new PokemonPpRestoreReward("modifierType:ModifierType.ETHER", "ether", RewardId.ETHER, 10),
|
||||||
new PokemonPpRestoreReward("modifierType:ModifierType.ETHER", "ether", RewardId.ETHER, 10);
|
[RewardId.MAX_ETHER]: new PokemonPpRestoreReward(
|
||||||
allRewards[RewardId.MAX_ETHER] = () =>
|
"modifierType:ModifierType.MAX_ETHER",
|
||||||
new PokemonPpRestoreReward("modifierType:ModifierType.MAX_ETHER", "max_ether", RewardId.MAX_ETHER, -1);
|
"max_ether",
|
||||||
|
RewardId.MAX_ETHER,
|
||||||
|
-1,
|
||||||
|
),
|
||||||
|
|
||||||
allRewards[RewardId.ELIXIR] = () =>
|
[RewardId.ELIXIR]: new PokemonAllMovePpRestoreReward(
|
||||||
new PokemonAllMovePpRestoreReward("modifierType:ModifierType.ELIXIR", "elixir", RewardId.ELIXIR, 10);
|
"modifierType:ModifierType.ELIXIR",
|
||||||
allRewards[RewardId.MAX_ELIXIR] = () =>
|
"elixir",
|
||||||
new PokemonAllMovePpRestoreReward("modifierType:ModifierType.MAX_ELIXIR", "max_elixir", RewardId.MAX_ELIXIR, -1);
|
RewardId.ELIXIR,
|
||||||
|
10,
|
||||||
|
),
|
||||||
|
[RewardId.MAX_ELIXIR]: new PokemonAllMovePpRestoreReward(
|
||||||
|
"modifierType:ModifierType.MAX_ELIXIR",
|
||||||
|
"max_elixir",
|
||||||
|
RewardId.MAX_ELIXIR,
|
||||||
|
-1,
|
||||||
|
),
|
||||||
|
|
||||||
allRewards[RewardId.PP_UP] = () =>
|
[RewardId.PP_UP]: new PokemonPpUpReward("modifierType:ModifierType.PP_UP", "pp_up", RewardId.PP_UP, 1),
|
||||||
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.PP_MAX] = () =>
|
|
||||||
new PokemonPpUpReward("modifierType:ModifierType.PP_MAX", "pp_max", RewardId.PP_MAX, 3);
|
|
||||||
|
|
||||||
/*REPEL] = () => new DoubleBattleChanceBoosterReward('Repel', 5),
|
[RewardId.MINT]: new MintRewardGenerator(),
|
||||||
SUPER_REPEL] = () => new DoubleBattleChanceBoosterReward('Super Repel', 10),
|
|
||||||
MAX_REPEL] = () => new DoubleBattleChanceBoosterReward('Max Repel', 25),*/
|
|
||||||
|
|
||||||
allRewards[RewardId.MINT] = () => new MintRewardGenerator();
|
[RewardId.TERA_SHARD]: new TeraTypeRewardGenerator(),
|
||||||
|
|
||||||
allRewards[RewardId.TERA_SHARD] = () => new TeraTypeRewardGenerator();
|
[RewardId.TM_COMMON]: new TmRewardGenerator(RarityTier.COMMON),
|
||||||
|
[RewardId.TM_GREAT]: new TmRewardGenerator(RarityTier.GREAT),
|
||||||
|
[RewardId.TM_ULTRA]: new TmRewardGenerator(RarityTier.ULTRA),
|
||||||
|
|
||||||
allRewards[RewardId.TM_COMMON] = () => new TmRewardGenerator(RarityTier.COMMON);
|
[RewardId.MEMORY_MUSHROOM]: new RememberMoveReward("modifierType:ModifierType.MEMORY_MUSHROOM", "big_mushroom"),
|
||||||
allRewards[RewardId.TM_GREAT] = () => new TmRewardGenerator(RarityTier.GREAT);
|
|
||||||
allRewards[RewardId.TM_ULTRA] = () => new TmRewardGenerator(RarityTier.ULTRA);
|
|
||||||
|
|
||||||
allRewards[RewardId.MEMORY_MUSHROOM] = () =>
|
[RewardId.DNA_SPLICERS]: new FusePokemonReward("modifierType:ModifierType.DNA_SPLICERS", "dna_splicers"),
|
||||||
new RememberMoveReward("modifierType:ModifierType.MEMORY_MUSHROOM", "big_mushroom");
|
|
||||||
|
|
||||||
allRewards[RewardId.DNA_SPLICERS] = () =>
|
|
||||||
new FusePokemonReward("modifierType:ModifierType.DNA_SPLICERS", "dna_splicers");
|
|
||||||
|
|
||||||
// Form change items
|
// Form change items
|
||||||
allRewards[RewardId.FORM_CHANGE_ITEM] = () => new FormChangeItemRewardGenerator(false, RewardId.FORM_CHANGE_ITEM);
|
[RewardId.FORM_CHANGE_ITEM]: new FormChangeItemRewardGenerator(false, RewardId.FORM_CHANGE_ITEM),
|
||||||
allRewards[RewardId.RARE_FORM_CHANGE_ITEM] = () =>
|
[RewardId.RARE_FORM_CHANGE_ITEM]: new FormChangeItemRewardGenerator(true, RewardId.RARE_FORM_CHANGE_ITEM),
|
||||||
new FormChangeItemRewardGenerator(true, RewardId.RARE_FORM_CHANGE_ITEM);
|
|
||||||
|
|
||||||
// Held items
|
// Held items
|
||||||
|
|
||||||
allRewards[RewardId.SPECIES_STAT_BOOSTER] = () => new SpeciesStatBoosterRewardGenerator(false);
|
[RewardId.SPECIES_STAT_BOOSTER]: new SpeciesStatBoosterRewardGenerator(false),
|
||||||
allRewards[RewardId.RARE_SPECIES_STAT_BOOSTER] = () => new SpeciesStatBoosterRewardGenerator(true);
|
[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),
|
|
||||||
|
|
||||||
// Trainer items
|
// Trainer items
|
||||||
|
|
||||||
allRewards[RewardId.LURE] = () => new LapsingTrainerItemReward(TrainerItemId.LURE, RewardId.LURE);
|
[RewardId.LURE]: new LapsingTrainerItemReward(TrainerItemId.LURE, RewardId.LURE),
|
||||||
allRewards[RewardId.SUPER_LURE] = () => new LapsingTrainerItemReward(TrainerItemId.SUPER_LURE, RewardId.SUPER_LURE);
|
[RewardId.SUPER_LURE]: new LapsingTrainerItemReward(TrainerItemId.SUPER_LURE, RewardId.SUPER_LURE),
|
||||||
allRewards[RewardId.MAX_LURE] = () => new LapsingTrainerItemReward(TrainerItemId.MAX_LURE, RewardId.MAX_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] = () =>
|
[RewardId.DIRE_HIT]: new LapsingTrainerItemReward(TrainerItemId.DIRE_HIT, RewardId.TEMP_STAT_STAGE_BOOSTER),
|
||||||
new LapsingTrainerItemReward(TrainerItemId.DIRE_HIT, RewardId.TEMP_STAT_STAGE_BOOSTER);
|
} as const satisfies {
|
||||||
// GOLDEN_POKEBALL] = () => new TrainerItemReward(TrainerItemId.GOLDEN_POKEBALL),
|
[k in RewardId]: Reward | RewardGenerator;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export type allRewardsType = typeof allRewards;
|
||||||
|
@ -8,7 +8,7 @@ import { isNullOrUndefined, pickWeightedIndex, randSeedInt } from "#utils/common
|
|||||||
import { getPartyLuckValue } from "#utils/party";
|
import { getPartyLuckValue } from "#utils/party";
|
||||||
import type { RewardOption } from "./reward";
|
import type { RewardOption } from "./reward";
|
||||||
import { rewardPool, rewardPoolWeights } from "./reward-pools";
|
import { rewardPool, rewardPoolWeights } from "./reward-pools";
|
||||||
import { generateRewardOptionFromId, generateRewardOptionFromSpecs, isTrainerItemId } from "./reward-utils";
|
import { generateRewardOptionFromId, isTrainerItemId } from "./reward-utils";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file still contains several functions to generate rewards from pools. The hierarchy of these functions is explained here.
|
This file still contains several functions to generate rewards from pools. The hierarchy of these functions is explained here.
|
||||||
@ -160,7 +160,7 @@ export function generatePlayerRewardOptions(
|
|||||||
|
|
||||||
if (customRewardSettings?.guaranteedRewardSpecs && customRewardSettings.guaranteedRewardSpecs.length > 0) {
|
if (customRewardSettings?.guaranteedRewardSpecs && customRewardSettings.guaranteedRewardSpecs.length > 0) {
|
||||||
for (const specs of customRewardSettings.guaranteedRewardSpecs) {
|
for (const specs of customRewardSettings.guaranteedRewardSpecs) {
|
||||||
const rewardOption = generateRewardOptionFromSpecs(specs);
|
const rewardOption = generateRewardOptionFromId(specs);
|
||||||
if (rewardOption) {
|
if (rewardOption) {
|
||||||
options.push(rewardOption);
|
options.push(rewardOption);
|
||||||
}
|
}
|
||||||
@ -287,13 +287,12 @@ function getNewRewardOption(
|
|||||||
* Replaces the {@linkcode Reward} of the entries within {@linkcode options} with any
|
* Replaces the {@linkcode Reward} of the entries within {@linkcode options} with any
|
||||||
* up to the smallest amount of entries between {@linkcode options} and the override array.
|
* up to the smallest amount of entries between {@linkcode options} and the override array.
|
||||||
* @param options Array of naturally rolled {@linkcode RewardOption}s
|
* @param options Array of naturally rolled {@linkcode RewardOption}s
|
||||||
* @param party Array of the player's current party
|
|
||||||
*/
|
*/
|
||||||
export function overridePlayerRewardOptions(options: RewardOption[]) {
|
export function overridePlayerRewardOptions(options: RewardOption[]) {
|
||||||
const minLength = Math.min(options.length, Overrides.REWARD_OVERRIDE.length);
|
const minLength = Math.min(options.length, Overrides.REWARD_OVERRIDE.length);
|
||||||
for (let i = 0; i < minLength; i++) {
|
for (let i = 0; i < minLength; i++) {
|
||||||
const specs: RewardSpecs = Overrides.REWARD_OVERRIDE[i];
|
const specs: RewardSpecs = Overrides.REWARD_OVERRIDE[i];
|
||||||
const rewardOption = generateRewardOptionFromSpecs(specs);
|
const rewardOption = generateRewardOptionFromId(specs);
|
||||||
if (rewardOption) {
|
if (rewardOption) {
|
||||||
options[i] = rewardOption;
|
options[i] = rewardOption;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
|
||||||
import { allRewards } from "#data/data-lists";
|
|
||||||
import type { HeldItemId } from "#enums/held-item-id";
|
import type { HeldItemId } from "#enums/held-item-id";
|
||||||
import { getRewardCategory, RewardCategoryId, RewardId } from "#enums/reward-id";
|
import { getRewardCategory, RewardCategoryId, RewardId } from "#enums/reward-id";
|
||||||
import type { RarityTier } from "#enums/reward-tier";
|
import type { RarityTier } from "#enums/reward-tier";
|
||||||
import type { TrainerItemId } from "#enums/trainer-item-id";
|
import type { TrainerItemId } from "#enums/trainer-item-id";
|
||||||
import type { RewardFunc, RewardPoolId, RewardSpecs } from "#types/rewards";
|
import { allRewards } from "#items/all-rewards";
|
||||||
|
import type { RewardPoolId, RewardSpecs } from "#types/rewards";
|
||||||
import { heldItemRarities } from "./held-item-default-tiers";
|
import { heldItemRarities } from "./held-item-default-tiers";
|
||||||
import {
|
import {
|
||||||
HeldItemReward,
|
HeldItemReward,
|
||||||
@ -33,22 +32,24 @@ export function isRememberMoveReward(reward: Reward): reward is RememberMoveRewa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a Reward from a given function
|
* Dynamically generate a {@linkcode RewardOption} from a given RewardSpecs.
|
||||||
* @param rewardFunc
|
* @param specs - The {@linkcode RewardSpecs} used to generate the reward
|
||||||
* @param pregenArgs Can specify BerryType for berries, TM for TMs, AttackBoostType for item, etc.
|
* @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 generateReward(rewardFunc: RewardFunc, pregenArgs?: any[]): Reward | null {
|
export function generateRewardOptionFromId<T extends RewardPoolId>(
|
||||||
const reward = rewardFunc();
|
specs: RewardSpecs<T>,
|
||||||
return reward instanceof RewardGenerator ? reward.generateReward(globalScene.getPlayerParty(), pregenArgs) : reward;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateRewardOptionFromId(
|
|
||||||
id: RewardPoolId,
|
|
||||||
cost = 0,
|
cost = 0,
|
||||||
tierOverride?: RarityTier,
|
tierOverride?: RarityTier,
|
||||||
upgradeCount = 0,
|
upgradeCount = 0,
|
||||||
pregenArgs?: any[],
|
|
||||||
): RewardOption | null {
|
): RewardOption | null {
|
||||||
|
// 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)) {
|
if (isHeldItemId(id)) {
|
||||||
const reward = new HeldItemReward(id);
|
const reward = new HeldItemReward(id);
|
||||||
const tier = tierOverride ?? heldItemRarities[id];
|
const tier = tierOverride ?? heldItemRarities[id];
|
||||||
@ -61,8 +62,8 @@ export function generateRewardOptionFromId(
|
|||||||
return new RewardOption(reward, upgradeCount, tier, cost);
|
return new RewardOption(reward, upgradeCount, tier, cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rewardFunc = allRewards[id];
|
const rewardFunc = allRewards[id] as Reward | RewardGenerator;
|
||||||
const reward = generateReward(rewardFunc, pregenArgs);
|
const reward = rewardFunc instanceof RewardGenerator ? rewardFunc.generateReward(pregenArgs) : rewardFunc;
|
||||||
if (reward) {
|
if (reward) {
|
||||||
const tier = tierOverride ?? rewardRarities[id];
|
const tier = tierOverride ?? rewardRarities[id];
|
||||||
return new RewardOption(reward, upgradeCount, tier, cost);
|
return new RewardOption(reward, upgradeCount, tier, cost);
|
||||||
@ -70,17 +71,6 @@ export function generateRewardOptionFromId(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateRewardOptionFromSpecs(
|
|
||||||
specs: RewardSpecs,
|
|
||||||
cost = 0,
|
|
||||||
overrideTier?: RarityTier,
|
|
||||||
): RewardOption | null {
|
|
||||||
if (typeof specs === "number") {
|
|
||||||
return generateRewardOptionFromId(specs, cost, overrideTier);
|
|
||||||
}
|
|
||||||
return generateRewardOptionFromId(specs.id, cost, overrideTier, 0, specs.args);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getPlayerShopRewardOptionsForWave(waveIndex: number, baseCost: number): RewardOption[] {
|
export function getPlayerShopRewardOptionsForWave(waveIndex: number, baseCost: number): RewardOption[] {
|
||||||
if (!(waveIndex % 10)) {
|
if (!(waveIndex % 10)) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -11,16 +11,16 @@ import { getNatureName, getNatureStatMultiplier } from "#data/nature";
|
|||||||
import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS } from "#data/pokeball";
|
import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS } from "#data/pokeball";
|
||||||
import { pokemonFormChanges, SpeciesFormChangeCondition } from "#data/pokemon-forms";
|
import { pokemonFormChanges, SpeciesFormChangeCondition } from "#data/pokemon-forms";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import type { BerryType } from "#enums/berry-type";
|
||||||
import { FormChangeItem } from "#enums/form-change-item";
|
import { FormChangeItem } from "#enums/form-change-item";
|
||||||
import { HeldItemId } from "#enums/held-item-id";
|
import { HeldItemId } from "#enums/held-item-id";
|
||||||
import { LearnMoveType } from "#enums/learn-move-type";
|
import { LearnMoveType } from "#enums/learn-move-type";
|
||||||
import { MoveId } from "#enums/move-id";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { RewardId } from "#enums/reward-id";
|
import { RewardId } from "#enums/reward-id";
|
||||||
import { RarityTier } from "#enums/reward-tier";
|
import type { RarityTier } from "#enums/reward-tier";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import type { PermanentStat, TempBattleStat } from "#enums/stat";
|
import type { PermanentStat, TempBattleStat } from "#enums/stat";
|
||||||
@ -32,65 +32,71 @@ import { permanentStatToHeldItem, statBoostItems } from "#items/base-stat-booste
|
|||||||
import { berryTypeToHeldItem } from "#items/berry";
|
import { berryTypeToHeldItem } from "#items/berry";
|
||||||
import { getNewAttackTypeBoosterHeldItem, getNewBerryHeldItem, getNewVitaminHeldItem } from "#items/held-item-pool";
|
import { getNewAttackTypeBoosterHeldItem, getNewBerryHeldItem, getNewVitaminHeldItem } from "#items/held-item-pool";
|
||||||
import { formChangeItemName } from "#items/item-utility";
|
import { formChangeItemName } from "#items/item-utility";
|
||||||
import { SPECIES_STAT_BOOSTER_ITEMS, type SpeciesStatBoostHeldItem } from "#items/stat-booster";
|
import type { SpeciesStatBoosterItemId, SpeciesStatBoostHeldItem } from "#items/stat-booster";
|
||||||
import { TrainerItemEffect, tempStatToTrainerItem } from "#items/trainer-item";
|
import { TrainerItemEffect, tempStatToTrainerItem } from "#items/trainer-item";
|
||||||
import type { PokemonMove } from "#moves/pokemon-move";
|
import type { PokemonMove } from "#moves/pokemon-move";
|
||||||
import { getVoucherTypeIcon, getVoucherTypeName, type VoucherType } from "#system/voucher";
|
import { getVoucherTypeIcon, getVoucherTypeName, type VoucherType } from "#system/voucher";
|
||||||
import type { Exact } from "#types/type-helpers";
|
import type { Exact } from "#types/type-helpers";
|
||||||
import type { PokemonMoveSelectFilter, PokemonSelectFilter } from "#ui/party-ui-handler";
|
import type { PokemonMoveSelectFilter, PokemonSelectFilter } from "#ui/party-ui-handler";
|
||||||
import { PartyUiHandler } 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 { getEnumKeys, getEnumValues } from "#utils/enums";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
/*
|
/**
|
||||||
The term "Reward" refers to items the player can access in the post-battle screen (although
|
* @module
|
||||||
they may be used in other places of the code as well).
|
* The term "Reward" refers to items the player can access in the post-battle screen (although
|
||||||
|
* they may be used in other places of the code as well).
|
||||||
|
|
||||||
Examples include (but are not limited to):
|
* Examples include (but are not limited to):
|
||||||
- Potions and other healing items
|
* - Potions and other healing items
|
||||||
- Held items and trainer items
|
* - Held items and trainer items
|
||||||
- Money items such as nugget and ancient relic
|
* - Money items such as nugget and ancient relic
|
||||||
|
|
||||||
Rewards have a basic structure with a name, description, and icon. These are used to display
|
* Rewards have a basic structure with a name, description, and icon. These are used to display
|
||||||
the reward in the reward select screen. All rewards have an .apply() method, which applies the
|
* the reward in the reward select screen. All rewards have an .apply() method, which applies the
|
||||||
effect, for example:
|
* effect, for example:
|
||||||
- Apply healing to a pokemon
|
* - Apply healing to a pokemon
|
||||||
- Assign a held item to a pokemon, or a trainer item to the player
|
* - Assign a held item to a pokemon, or a trainer item to the player
|
||||||
- Add money
|
* - Add money
|
||||||
|
|
||||||
Some rewards, once clicked, simply have their effect---these are Rewards that add money, pokéball,
|
* Some rewards, once clicked, simply have their effect---these are Rewards that add money, pokéball,
|
||||||
vouchers, or global effect such as Sacred Ash.
|
* vouchers, or global effect such as Sacred Ash.
|
||||||
Most rewards require extra parameters. They are divided into subclasses depending on the parameters
|
* Most rewards require extra parameters. They are divided into subclasses depending on the parameters
|
||||||
that they need, in particular:
|
* that they need, in particular:
|
||||||
- PokemonReward requires to pass a Pokemon (to apply healing, assign item...)
|
* - PokemonReward requires to pass a Pokemon (to apply healing, assign item...)
|
||||||
- PokemonMoveReward requires to pass a Pokemon and a move (for Elixir, or PP Up)
|
* - PokemonMoveReward requires to pass a Pokemon and a move (for Elixir, or PP Up)
|
||||||
Plus some edge cases for Memory Mushroom and DNA Splicers.
|
* Plus some edge cases for Memory Mushroom and DNA Splicers.
|
||||||
|
|
||||||
The parameters to be passed are generated by the .applyReward() function in SelectRewardPhase.
|
* The parameters to be passed are generated by the .applyReward() function in {@linkcode SelectRewardPhase}.
|
||||||
This function takes care of opening the party screen and letting the player select a party pokemon,
|
* This function takes care of opening the party screen and letting the player select a party pokemon,
|
||||||
a move, etc. depending on what is required. Once the parameters are generated, instead of calling
|
* a move, etc. depending on what is required. Once the parameters are generated, instead of calling
|
||||||
.apply() directly, we call the .applyReward() method in BattleScene, which also plays the sound.
|
* .apply() directly, we call the .applyReward() method in BattleScene, which also plays the sound.
|
||||||
[This method could perhaps be removed].
|
* [This method could perhaps be removed].
|
||||||
|
|
||||||
Rewards are assigned RewardId, and there are also RewardCategoryId. For example, TM is a RewardCategoryId,
|
* Rewards are assigned RewardId, and there are also RewardCategoryId. For example, TM is a RewardCategoryId,
|
||||||
while CommonTM, RareTM etc are RewardIds. There is _not_ a RewardId for _each_ move. Similarly,
|
* while CommonTM, RareTM etc are RewardIds. There is _not_ a RewardId for _each_ move. Similarly,
|
||||||
some specific categories of held items are assigned their own RewardId, but they all fall under a single
|
* some specific categories of held items are assigned their own RewardId, but they all fall under a single
|
||||||
RewardCategoryId.
|
* RewardCategoryId.
|
||||||
|
|
||||||
rewardInitObj plays a similar role to allHeldItems, except instead of containing all possible reward
|
* rewardInitObj plays a similar role to allHeldItems, except instead of containing all possible reward
|
||||||
instances, it instead contains functions that generate those rewards. Here, the keys used are strings
|
* instances, it instead contains functions that generate those rewards. Here, the keys used are strings
|
||||||
rather than RewardId, the difference exists because here we want to distinguish unique held items
|
* rather than RewardId, the difference exists because here we want to distinguish unique held items
|
||||||
for example. The entries of rewardInitObj are used in the RewardPool.
|
* for example. The entries of rewardInitObj are used in the RewardPool.
|
||||||
|
|
||||||
There are some more derived classes, in particular:
|
* There are some more derived classes, in particular:
|
||||||
RewardGenerator, which creates Reward instances from a certain group (e.g. TMs, nature mints, or berries);
|
* RewardGenerator, which creates Reward instances from a certain group (e.g. TMs, nature mints, or berries);
|
||||||
and RewardOption, which is displayed during the select reward phase at the end of each encounter.
|
* and RewardOption, which is displayed during the select reward phase at the end of each encounter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type helper to exactly match objects and nothing else.
|
||||||
|
* @todo merge with `Exact` later on
|
||||||
|
*/
|
||||||
|
export type MatchExact<T> = T extends object ? Exact<T> : T;
|
||||||
|
|
||||||
export abstract class Reward {
|
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: 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 id: RewardId;
|
||||||
public localeKey: string;
|
public localeKey: string;
|
||||||
public iconImage: string;
|
public iconImage: string;
|
||||||
@ -109,6 +115,7 @@ export abstract class Reward {
|
|||||||
return i18next.t(`${this.localeKey}.name`);
|
return i18next.t(`${this.localeKey}.name`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: These should be getters
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
return i18next.t(`${this.localeKey}.description`);
|
return i18next.t(`${this.localeKey}.description`);
|
||||||
}
|
}
|
||||||
@ -121,8 +128,8 @@ export abstract class Reward {
|
|||||||
/**
|
/**
|
||||||
* Check whether this reward should be applied.
|
* Check whether this reward should be applied.
|
||||||
*/
|
*/
|
||||||
// TODO: This is erroring on stuff of typ
|
// TODO: This is erroring on stuff with `undefined`
|
||||||
shouldApply(_params: Exact<Parameters<this["apply"]>[0]>): boolean {
|
shouldApply(_params: MatchExact<Parameters<this["apply"]>[0]>): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,25 +138,18 @@ export abstract class Reward {
|
|||||||
abstract apply(_params?: unknown): void;
|
abstract apply(_params?: unknown): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Can this return null?
|
/**
|
||||||
// TODO: Make this generic based on T
|
* A {@linkcode RewardGenerator} represents a dynamic generator for a given type of reward.
|
||||||
type RewardGeneratorFunc<T extends Reward> = (party: Pokemon[], pregenArgs?: any[]) => T | null;
|
* These can be customized by lieu of {@linkcode generateReward} to alter the generation result.
|
||||||
|
*/
|
||||||
export abstract class RewardGenerator<T extends Reward = Reward> {
|
export abstract class RewardGenerator {
|
||||||
private genRewardFunc: RewardGeneratorFunc<T>;
|
/**
|
||||||
public id: RewardId;
|
* Dynamically generate a new reward.
|
||||||
|
* @param pregenArgs - An optional argument taken by super classes to customize the reward generated.
|
||||||
constructor(genRewardFunc: RewardGeneratorFunc<T>) {
|
* @returns The generated reward, or `null` if none are able to be produced
|
||||||
this.genRewardFunc = genRewardFunc;
|
*/
|
||||||
}
|
// TODO: Remove null from signature in favor of adding a condition or similar (reduces bangs needed)
|
||||||
|
abstract generateReward(pregenArgs?: unknown): Reward | null;
|
||||||
generateReward(party: Pokemon[], pregenArgs?: any[]) {
|
|
||||||
const ret = this.genRewardFunc(party, pregenArgs);
|
|
||||||
if (ret && this.id) {
|
|
||||||
ret.id = this.id;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AddPokeballReward extends Reward {
|
export class AddPokeballReward extends Reward {
|
||||||
@ -370,6 +370,7 @@ export class HeldItemReward extends PokemonReward {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TrainerItemReward extends Reward {
|
export class TrainerItemReward extends Reward {
|
||||||
|
// TODO: This should not be public
|
||||||
public itemId: TrainerItemId;
|
public itemId: TrainerItemId;
|
||||||
constructor(itemId: TrainerItemId, group?: string, soundName?: string) {
|
constructor(itemId: TrainerItemId, group?: string, soundName?: string) {
|
||||||
super("", "", group, soundName);
|
super("", "", group, soundName);
|
||||||
@ -461,33 +462,48 @@ export class ChangeTeraTypeReward extends PokemonReward {
|
|||||||
pokemon.teraType = this.teraType;
|
pokemon.teraType = this.teraType;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} // 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(
|
function restorePokemonHp(
|
||||||
pokemon: Pokemon,
|
pokemon: Pokemon,
|
||||||
percentToRestore: number,
|
percentToRestore: number,
|
||||||
|
{
|
||||||
pointsToRestore = 0,
|
pointsToRestore = 0,
|
||||||
healStatus = false,
|
healStatus = false,
|
||||||
fainted = false,
|
fainted = false,
|
||||||
|
}: {
|
||||||
|
pointsToRestore?: number;
|
||||||
|
healStatus?: boolean;
|
||||||
|
fainted?: boolean;
|
||||||
|
} = {},
|
||||||
): boolean {
|
): boolean {
|
||||||
if (!pokemon.hp === fainted) {
|
if (pokemon.isFainted() !== fainted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (fainted || healStatus) {
|
if (fainted || healStatus) {
|
||||||
pokemon.resetStatus(true, true, false, false);
|
pokemon.resetStatus(true, true, false, false);
|
||||||
}
|
}
|
||||||
// Apply HealingCharm
|
// Apply HealingCharm
|
||||||
let multiplier = 1;
|
|
||||||
if (!fainted) {
|
|
||||||
const hpRestoreMultiplier = new NumberHolder(1);
|
const hpRestoreMultiplier = new NumberHolder(1);
|
||||||
|
if (!fainted) {
|
||||||
this.applyPlayerItems(TrainerItemEffect.HEALING_BOOSTER, { numberHolder: hpRestoreMultiplier });
|
this.applyPlayerItems(TrainerItemEffect.HEALING_BOOSTER, { numberHolder: hpRestoreMultiplier });
|
||||||
multiplier = hpRestoreMultiplier.value;
|
|
||||||
}
|
}
|
||||||
const restorePoints = Math.floor(pointsToRestore * multiplier);
|
const restorePoints = toDmgValue(pointsToRestore * hpRestoreMultiplier.value);
|
||||||
const restorePercent = Math.floor(percentToRestore * 0.01 * multiplier * pokemon.getMaxHp());
|
const restorePercent = toDmgValue((percentToRestore / 100) * hpRestoreMultiplier.value * pokemon.getMaxHp());
|
||||||
pokemon.heal(Math.max(restorePercent, restorePoints, 1));
|
pokemon.heal(Math.max(restorePercent, restorePoints));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonHpRestoreReward extends PokemonReward {
|
export class PokemonHpRestoreReward extends PokemonReward {
|
||||||
protected restorePoints: number;
|
protected restorePoints: number;
|
||||||
@ -854,59 +870,55 @@ export class RememberMoveReward extends PokemonReward {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class BerryRewardGenerator extends RewardGenerator {
|
export class BerryRewardGenerator extends RewardGenerator {
|
||||||
constructor() {
|
override generateReward(pregenArgs?: BerryType): HeldItemReward {
|
||||||
super((_party: Pokemon[], pregenArgs?: any[]) => {
|
if (pregenArgs !== undefined) {
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in BerryType) {
|
const item = berryTypeToHeldItem[pregenArgs];
|
||||||
const item = berryTypeToHeldItem[pregenArgs[0] as BerryType];
|
|
||||||
return new HeldItemReward(item);
|
return new HeldItemReward(item);
|
||||||
}
|
}
|
||||||
const item = getNewBerryHeldItem();
|
const item = getNewBerryHeldItem();
|
||||||
return new HeldItemReward(item);
|
return new HeldItemReward(item);
|
||||||
});
|
|
||||||
this.id = RewardId.BERRY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MintRewardGenerator extends RewardGenerator {
|
export class MintRewardGenerator extends RewardGenerator {
|
||||||
constructor() {
|
override generateReward(pregenArgs?: Nature) {
|
||||||
super((_party: Pokemon[], pregenArgs?: any[]) => {
|
if (pregenArgs !== undefined) {
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in Nature) {
|
return new PokemonNatureChangeReward(pregenArgs);
|
||||||
return new PokemonNatureChangeReward(pregenArgs[0] as Nature);
|
|
||||||
}
|
}
|
||||||
return new PokemonNatureChangeReward(randSeedItem(getEnumValues(Nature)));
|
return new PokemonNatureChangeReward(randSeedItem(getEnumValues(Nature)));
|
||||||
});
|
|
||||||
this.id = RewardId.MINT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TeraTypeRewardGenerator extends RewardGenerator {
|
export class TeraTypeRewardGenerator extends RewardGenerator {
|
||||||
constructor() {
|
override generateReward(pregenArgs?: PokemonType) {
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
if (pregenArgs !== undefined) {
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in PokemonType) {
|
return new ChangeTeraTypeReward(pregenArgs[0]);
|
||||||
return new ChangeTeraTypeReward(pregenArgs[0] as PokemonType);
|
|
||||||
}
|
}
|
||||||
if (!globalScene.trainerItems.hasItem(TrainerItemId.TERA_ORB)) {
|
if (!globalScene.trainerItems.hasItem(TrainerItemId.TERA_ORB)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const teraTypes: PokemonType[] = [];
|
|
||||||
for (const p of party) {
|
const shardType = this.getTeraType();
|
||||||
if (
|
|
||||||
!(p.hasSpecies(SpeciesId.TERAPAGOS) || p.hasSpecies(SpeciesId.OGERPON) || p.hasSpecies(SpeciesId.SHEDINJA))
|
|
||||||
) {
|
|
||||||
teraTypes.push(p.teraType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let excludedType = PokemonType.UNKNOWN;
|
|
||||||
if (teraTypes.length > 0 && teraTypes.filter(t => t === teraTypes[0]).length === teraTypes.length) {
|
|
||||||
excludedType = teraTypes[0];
|
|
||||||
}
|
|
||||||
let shardType = randSeedInt(64) ? (randSeedInt(18) as PokemonType) : PokemonType.STELLAR;
|
|
||||||
while (shardType === excludedType) {
|
|
||||||
shardType = randSeedInt(64) ? (randSeedInt(18) as PokemonType) : PokemonType.STELLAR;
|
|
||||||
}
|
|
||||||
return new ChangeTeraTypeReward(shardType);
|
return new ChangeTeraTypeReward(shardType);
|
||||||
});
|
}
|
||||||
this.id = RewardId.TERA_SHARD;
|
|
||||||
|
private getTeraType(): PokemonType {
|
||||||
|
// If all party members have a given Tera Type, omit it from the pool
|
||||||
|
const excludedType = globalScene.getPlayerParty().reduce((prevType, p) => {
|
||||||
|
if (
|
||||||
|
// Ignore Pokemon with fixed Tera Types
|
||||||
|
p.hasSpecies(SpeciesId.TERAPAGOS) ||
|
||||||
|
p.hasSpecies(SpeciesId.OGERPON) ||
|
||||||
|
p.hasSpecies(SpeciesId.SHEDINJA)
|
||||||
|
) {
|
||||||
|
return prevType;
|
||||||
|
}
|
||||||
|
return prevType === p.teraType ? prevType : PokemonType.UNKNOWN;
|
||||||
|
}, PokemonType.UNKNOWN);
|
||||||
|
|
||||||
|
const validTypes = getEnumValues(PokemonType).filter(t => t !== excludedType);
|
||||||
|
// 1/64 chance for tera stellar
|
||||||
|
return randSeedInt(64) ? randSeedItem(validTypes) : PokemonType.STELLAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1208,29 +1220,23 @@ export class FusePokemonReward extends PokemonReward {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AttackTypeBoosterRewardGenerator extends RewardGenerator {
|
export class AttackTypeBoosterRewardGenerator extends RewardGenerator {
|
||||||
constructor() {
|
override generateReward(pregenArgs?: PokemonType) {
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
if (pregenArgs !== undefined) {
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in PokemonType) {
|
return new AttackTypeBoosterReward(pregenArgs, TYPE_BOOST_ITEM_BOOST_PERCENT);
|
||||||
return new AttackTypeBoosterReward(pregenArgs[0] as PokemonType, TYPE_BOOST_ITEM_BOOST_PERCENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = getNewAttackTypeBoosterHeldItem(party);
|
const item = getNewAttackTypeBoosterHeldItem(globalScene.getPlayerParty());
|
||||||
|
|
||||||
return item ? new HeldItemReward(item) : null;
|
return item ? new HeldItemReward(item) : null;
|
||||||
});
|
|
||||||
this.id = RewardId.ATTACK_TYPE_BOOSTER;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseStatBoosterRewardGenerator extends RewardGenerator {
|
export class BaseStatBoosterRewardGenerator extends RewardGenerator {
|
||||||
constructor() {
|
override generateReward(pregenArgs?: PermanentStat) {
|
||||||
super((_party: Pokemon[], pregenArgs?: any[]) => {
|
if (pregenArgs !== undefined) {
|
||||||
if (pregenArgs) {
|
return new BaseStatBoosterReward(pregenArgs);
|
||||||
return new BaseStatBoosterReward(pregenArgs[0]);
|
|
||||||
}
|
}
|
||||||
return new HeldItemReward(getNewVitaminHeldItem());
|
return new HeldItemReward(getNewVitaminHeldItem());
|
||||||
});
|
|
||||||
this.id = RewardId.BASE_STAT_BOOSTER;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1244,15 +1250,8 @@ export class TempStatStageBoosterRewardGenerator extends RewardGenerator {
|
|||||||
[Stat.ACC]: "x_accuracy",
|
[Stat.ACC]: "x_accuracy",
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
override generateReward(pregenArgs?: TempBattleStat) {
|
||||||
super((_party: Pokemon[], pregenArgs?: any[]) => {
|
return new LapsingTrainerItemReward(tempStatToTrainerItem[pregenArgs ?? randSeedItem(TEMP_BATTLE_STATS)]);
|
||||||
if (pregenArgs && pregenArgs.length === 1 && TEMP_BATTLE_STATS.includes(pregenArgs[0])) {
|
|
||||||
return new LapsingTrainerItemReward(tempStatToTrainerItem[pregenArgs[0]]);
|
|
||||||
}
|
|
||||||
const randStat: TempBattleStat = randSeedInt(Stat.ACC, Stat.ATK);
|
|
||||||
return new LapsingTrainerItemReward(tempStatToTrainerItem[randStat]);
|
|
||||||
});
|
|
||||||
this.id = RewardId.TEMP_STAT_STAGE_BOOSTER;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1265,20 +1264,24 @@ export class TempStatStageBoosterRewardGenerator extends RewardGenerator {
|
|||||||
export class SpeciesStatBoosterRewardGenerator extends RewardGenerator {
|
export class SpeciesStatBoosterRewardGenerator extends RewardGenerator {
|
||||||
/** Object comprised of the currently available species-based stat boosting held items */
|
/** Object comprised of the currently available species-based stat boosting held items */
|
||||||
|
|
||||||
|
private rare: boolean;
|
||||||
constructor(rare: boolean) {
|
constructor(rare: boolean) {
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
super();
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in SPECIES_STAT_BOOSTER_ITEMS) {
|
this.rare = rare;
|
||||||
return new HeldItemReward(pregenArgs[0] as HeldItemId);
|
}
|
||||||
|
override generateReward(pregenArgs?: SpeciesStatBoosterItemId) {
|
||||||
|
if (pregenArgs !== undefined) {
|
||||||
|
return new HeldItemReward(pregenArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a pool of items based on the rarity.
|
// Get a pool of items based on the rarity.
|
||||||
const tierItems = rare
|
const tierItems = this.rare
|
||||||
? [HeldItemId.LIGHT_BALL, HeldItemId.THICK_CLUB, HeldItemId.METAL_POWDER, HeldItemId.QUICK_POWDER]
|
? [HeldItemId.LIGHT_BALL, HeldItemId.THICK_CLUB, HeldItemId.METAL_POWDER, HeldItemId.QUICK_POWDER]
|
||||||
: [HeldItemId.DEEP_SEA_SCALE, HeldItemId.DEEP_SEA_TOOTH];
|
: [HeldItemId.DEEP_SEA_SCALE, HeldItemId.DEEP_SEA_TOOTH];
|
||||||
|
|
||||||
const weights = new Array(tierItems.length).fill(0);
|
const weights = new Array(tierItems.length).fill(0);
|
||||||
|
|
||||||
for (const p of party) {
|
for (const p of globalScene.getPlayerParty()) {
|
||||||
const speciesId = p.getSpeciesForm(true).speciesId;
|
const speciesId = p.getSpeciesForm(true).speciesId;
|
||||||
const fusionSpeciesId = p.isFusion() ? p.getFusionSpeciesForm(true).speciesId : null;
|
const fusionSpeciesId = p.isFusion() ? p.getFusionSpeciesForm(true).speciesId : null;
|
||||||
// TODO: Use commented boolean when Fling is implemented
|
// TODO: Use commented boolean when Fling is implemented
|
||||||
@ -1324,17 +1327,22 @@ export class SpeciesStatBoosterRewardGenerator extends RewardGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
|
||||||
this.id = rare ? RewardId.SPECIES_STAT_BOOSTER : RewardId.RARE_SPECIES_STAT_BOOSTER;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TmRewardGenerator extends RewardGenerator {
|
export class TmRewardGenerator extends RewardGenerator {
|
||||||
|
private tier: RarityTier;
|
||||||
constructor(tier: RarityTier) {
|
constructor(tier: RarityTier) {
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
super();
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in MoveId) {
|
this.tier = tier;
|
||||||
return new TmReward(pregenArgs[0] as MoveId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override generateReward(pregenArgs?: MoveId) {
|
||||||
|
if (pregenArgs !== undefined) {
|
||||||
|
return new TmReward(pregenArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const party = globalScene.getPlayerParty();
|
||||||
const partyMemberCompatibleTms = party.map(p => {
|
const partyMemberCompatibleTms = party.map(p => {
|
||||||
const previousLevelMoves = p.getLearnableLevelMoves();
|
const previousLevelMoves = p.getLearnableLevelMoves();
|
||||||
return (p as PlayerPokemon).compatibleTms.filter(
|
return (p as PlayerPokemon).compatibleTms.filter(
|
||||||
@ -1343,32 +1351,32 @@ export class TmRewardGenerator extends RewardGenerator {
|
|||||||
});
|
});
|
||||||
const tierUniqueCompatibleTms = partyMemberCompatibleTms
|
const tierUniqueCompatibleTms = partyMemberCompatibleTms
|
||||||
.flat()
|
.flat()
|
||||||
.filter(tm => tmPoolTiers[tm] === tier)
|
.filter(tm => tmPoolTiers[tm] === this.tier)
|
||||||
.filter(tm => !allMoves[tm].name.endsWith(" (N)"))
|
.filter(tm => !allMoves[tm].name.endsWith(" (N)"))
|
||||||
.filter((tm, i, array) => array.indexOf(tm) === i);
|
.filter((tm, i, array) => array.indexOf(tm) === i);
|
||||||
if (!tierUniqueCompatibleTms.length) {
|
if (!tierUniqueCompatibleTms.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// TODO: should this use `randSeedItem`?
|
|
||||||
const randTmIndex = randSeedInt(tierUniqueCompatibleTms.length);
|
const randTmIndex = randSeedItem(tierUniqueCompatibleTms);
|
||||||
return new TmReward(tierUniqueCompatibleTms[randTmIndex]);
|
return new TmReward(randTmIndex);
|
||||||
});
|
|
||||||
this.id =
|
|
||||||
tier === RarityTier.COMMON
|
|
||||||
? RewardId.TM_COMMON
|
|
||||||
: tier === RarityTier.GREAT
|
|
||||||
? RewardId.TM_GREAT
|
|
||||||
: RewardId.TM_ULTRA;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EvolutionItemRewardGenerator extends RewardGenerator {
|
export class EvolutionItemRewardGenerator extends RewardGenerator {
|
||||||
constructor(rare: boolean, id: RewardId) {
|
private rare: boolean;
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
constructor(rare: boolean) {
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in EvolutionItem) {
|
super();
|
||||||
return new EvolutionItemReward(pregenArgs[0] as EvolutionItem);
|
this.rare = rare;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override generateReward(pregenArgs?: EvolutionItem) {
|
||||||
|
if (pregenArgs !== undefined) {
|
||||||
|
return new EvolutionItemReward(pregenArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const party = globalScene.getPlayerParty();
|
||||||
|
|
||||||
const evolutionItemPool = [
|
const evolutionItemPool = [
|
||||||
party
|
party
|
||||||
.filter(
|
.filter(
|
||||||
@ -1403,26 +1411,31 @@ export class EvolutionItemRewardGenerator extends RewardGenerator {
|
|||||||
]
|
]
|
||||||
.flat()
|
.flat()
|
||||||
.flatMap(e => e.evoItem)
|
.flatMap(e => e.evoItem)
|
||||||
.filter(i => !!i && i > 50 === rare);
|
.filter(i => !!i && i > 50 === this.rare);
|
||||||
|
|
||||||
if (!evolutionItemPool.length) {
|
if (!evolutionItemPool.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should this use `randSeedItem`?
|
return new EvolutionItemReward(randSeedItem(evolutionItemPool));
|
||||||
return new EvolutionItemReward(evolutionItemPool[randSeedInt(evolutionItemPool.length)]!); // TODO: is the bang correct?
|
|
||||||
});
|
|
||||||
this.id = id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FormChangeItemRewardGenerator extends RewardGenerator {
|
export class FormChangeItemRewardGenerator extends RewardGenerator {
|
||||||
constructor(isRareFormChangeItem: boolean, id: RewardId) {
|
private isRareFormChangeItem: boolean;
|
||||||
super((party: Pokemon[], pregenArgs?: any[]) => {
|
|
||||||
if (pregenArgs && pregenArgs.length === 1 && pregenArgs[0] in FormChangeItem) {
|
constructor(isRareFormChangeItem: boolean) {
|
||||||
return new FormChangeItemReward(pregenArgs[0] as FormChangeItem);
|
super();
|
||||||
|
this.isRareFormChangeItem = isRareFormChangeItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override generateReward(pregenArgs?: FormChangeItem) {
|
||||||
|
if (pregenArgs !== undefined) {
|
||||||
|
return new FormChangeItemReward(pregenArgs);
|
||||||
|
}
|
||||||
|
const party = globalScene.getPlayerParty();
|
||||||
|
|
||||||
|
// TODO: REFACTOR THIS FUCKERY PLEASE
|
||||||
const formChangeItemPool = [
|
const formChangeItemPool = [
|
||||||
...new Set(
|
...new Set(
|
||||||
party
|
party
|
||||||
@ -1480,17 +1493,14 @@ export class FormChangeItemRewardGenerator extends RewardGenerator {
|
|||||||
]
|
]
|
||||||
.flat()
|
.flat()
|
||||||
.flatMap(fc => fc.item)
|
.flatMap(fc => fc.item)
|
||||||
.filter(i => (i && i < 100) === isRareFormChangeItem);
|
.filter(i => (i && i < 100) === this.isRareFormChangeItem);
|
||||||
// convert it into a set to remove duplicate values, which can appear when the same species with a potential form change is in the party.
|
// convert it into a set to remove duplicate values, which can appear when the same species with a potential form change is in the party.
|
||||||
|
|
||||||
if (!formChangeItemPool.length) {
|
if (!formChangeItemPool.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should this use `randSeedItem`?
|
return new FormChangeItemReward(randSeedItem(formChangeItemPool));
|
||||||
return new FormChangeItemReward(formChangeItemPool[randSeedInt(formChangeItemPool.length)]);
|
|
||||||
});
|
|
||||||
this.id = id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1508,22 +1518,6 @@ export class RewardOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: If necessary, add the rest of the modifier types here.
|
export class NoneReward extends Reward {
|
||||||
// For now, doing the minimal work until the modifier rework lands.
|
override apply(): void {}
|
||||||
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<RewardConstructorMap[K]>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RewardString = keyof RewardConstructorMap;
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { Reward } from "#items/reward";
|
import type { Reward, RewardGenerator } from "#items/reward";
|
||||||
import { BattlePhase } from "#phases/battle-phase";
|
import { BattlePhase } from "#phases/battle-phase";
|
||||||
import type { RewardFunc } from "#types/rewards";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class RewardPhase extends BattlePhase {
|
export class RewardPhase extends BattlePhase {
|
||||||
@ -10,7 +9,7 @@ export class RewardPhase extends BattlePhase {
|
|||||||
public readonly phaseName: "RewardPhase" | "RibbonRewardPhase" | "GameOverRewardPhase" = "RewardPhase";
|
public readonly phaseName: "RewardPhase" | "RibbonRewardPhase" | "GameOverRewardPhase" = "RewardPhase";
|
||||||
protected reward: Reward;
|
protected reward: Reward;
|
||||||
|
|
||||||
constructor(rewardFunc: RewardFunc) {
|
constructor(rewardFunc: Reward | RewardGenerator) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.reward = rewardFunc();
|
this.reward = rewardFunc();
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
|
import type { Reward, RewardGenerator } from "#items/reward";
|
||||||
import { RewardPhase } from "#phases/reward-phase";
|
import { RewardPhase } from "#phases/reward-phase";
|
||||||
import type { RewardFunc } from "#types/rewards";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class RibbonRewardPhase extends RewardPhase {
|
export class RibbonRewardPhase extends RewardPhase {
|
||||||
public readonly phaseName = "RibbonRewardPhase";
|
public readonly phaseName = "RibbonRewardPhase";
|
||||||
private species: PokemonSpecies;
|
private species: PokemonSpecies;
|
||||||
|
|
||||||
constructor(rewardFunc: RewardFunc, species: PokemonSpecies) {
|
constructor(rewardFunc: Reward | RewardGenerator, species: PokemonSpecies) {
|
||||||
super(rewardFunc);
|
super(rewardFunc);
|
||||||
|
|
||||||
this.species = species;
|
this.species = species;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { Reward } from "#items/reward";
|
import { type Reward, RewardGenerator } from "#items/reward";
|
||||||
import { BattlePhase } from "#phases/battle-phase";
|
import { BattlePhase } from "#phases/battle-phase";
|
||||||
import type { RewardFunc } from "#types/rewards";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class RewardPhase extends BattlePhase {
|
export class RewardPhase extends BattlePhase {
|
||||||
@ -10,10 +9,11 @@ export class RewardPhase extends BattlePhase {
|
|||||||
public readonly phaseName: "RewardPhase" | "RibbonRewardPhase" | "GameOverRewardPhase" = "RewardPhase";
|
public readonly phaseName: "RewardPhase" | "RibbonRewardPhase" | "GameOverRewardPhase" = "RewardPhase";
|
||||||
protected reward: Reward;
|
protected reward: Reward;
|
||||||
|
|
||||||
constructor(rewardFunc: RewardFunc) {
|
constructor(rewardFunc: Reward | RewardGenerator) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.reward = rewardFunc();
|
const reward = rewardFunc();
|
||||||
|
this.reward = reward instanceof RewardGenerator ? reward.generateReward() : reward;
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
@ -5,8 +5,8 @@ import { Challenges } from "#enums/challenges";
|
|||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
|
||||||
import { TextStyle } from "#enums/text-style";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import { addTextObject } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import type { nil } from "#utils/common";
|
import type { nil } from "#utils/common";
|
||||||
|
@ -5,8 +5,8 @@ import { Button } from "#enums/buttons";
|
|||||||
import { Command } from "#enums/command";
|
import { Command } from "#enums/command";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { TrainerItemId } from "#enums/trainer-item-id";
|
|
||||||
import { TextStyle } from "#enums/text-style";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { TrainerItemId } from "#enums/trainer-item-id";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { CommandPhase } from "#phases/command-phase";
|
import type { CommandPhase } from "#phases/command-phase";
|
||||||
import { PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler";
|
import { PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler";
|
||||||
|
@ -2160,6 +2160,7 @@ class PartyDiscardModeButton extends Phaser.GameObjects.Container {
|
|||||||
* @remarks
|
* @remarks
|
||||||
* This will also reveal the button if it is currently hidden.
|
* This will also reveal the button if it is currently hidden.
|
||||||
*/
|
*/
|
||||||
|
// TODO: Reminder to fix
|
||||||
public toggleIcon(partyMode: PartyUiMode.MODIFIER_TRANSFER | PartyUiMode.DISCARD): void {
|
public toggleIcon(partyMode: PartyUiMode.MODIFIER_TRANSFER | PartyUiMode.DISCARD): void {
|
||||||
this.setActive(true).setVisible(true);
|
this.setActive(true).setVisible(true);
|
||||||
switch (partyMode) {
|
switch (partyMode) {
|
||||||
|
@ -125,8 +125,8 @@ export function randItem<T>(items: T[]): T {
|
|||||||
return items.length === 1 ? items[0] : items[randInt(items.length)];
|
return items.length === 1 ? items[0] : items[randInt(items.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function randSeedItem<T>(items: T[]): T {
|
export function randSeedItem<T>(items: T[] | readonly T[]): T {
|
||||||
return items.length === 1 ? items[0] : Phaser.Math.RND.pick(items);
|
return items.length === 1 ? items[0] : Phaser.Math.RND.pick(items as T[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function randSeedWeightedItem<T>(items: T[]): T {
|
export function randSeedWeightedItem<T>(items: T[]): T {
|
||||||
|
Loading…
Reference in New Issue
Block a user