mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-08 08:29:37 +02:00
[Challenge] Add Nuzlocke-related Challenges
Co-authored-by: =?UTF-8?q?Matilde=20Sim=C3=B5es?= <matilde.simoes@tecnico.ulisboa.pt> Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: Sirzento <sirzento@gmx.de>
This commit is contained in:
parent
1b8082a177
commit
ef7437815a
@ -13,15 +13,16 @@ import { Challenges } from "#enums/challenges";
|
|||||||
import { TypeColor, TypeShadow } from "#enums/color";
|
import { TypeColor, TypeShadow } from "#enums/color";
|
||||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||||
import { ModifierTier } from "#enums/modifier-tier";
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
import type { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import type { MoveSourceType } from "#enums/move-source-type";
|
import type { MoveSourceType } from "#enums/move-source-type";
|
||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
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 { 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 { Pokemon } from "#field/pokemon";
|
import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||||
import { Trainer } from "#field/trainer";
|
import { Trainer } from "#field/trainer";
|
||||||
|
import type { ModifierTypeOption } from "#modifiers/modifier-type";
|
||||||
import { PokemonMove } from "#moves/pokemon-move";
|
import { PokemonMove } from "#moves/pokemon-move";
|
||||||
import type { DexAttrProps, GameData } from "#system/game-data";
|
import type { DexAttrProps, GameData } from "#system/game-data";
|
||||||
import { BooleanHolder, type NumberHolder, randSeedItem } from "#utils/common";
|
import { BooleanHolder, type NumberHolder, randSeedItem } from "#utils/common";
|
||||||
@ -345,6 +346,75 @@ export abstract class Challenge {
|
|||||||
applyFlipStat(_pokemon: Pokemon, _baseStats: number[]) {
|
applyFlipStat(_pokemon: Pokemon, _baseStats: number[]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for PARTY_HEAL. Derived classes should alter this.
|
||||||
|
* @returns Whether party healing is enabled or not
|
||||||
|
*/
|
||||||
|
applyPartyHeal(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for SHOP. Derived classes should alter this.
|
||||||
|
* @returns Whether the shop is or is not available after a wave
|
||||||
|
*/
|
||||||
|
applyShop() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for POKEMON_ADD_TO_PARTY. Derived classes should alter this.
|
||||||
|
* @param _pokemon - The pokemon being caught
|
||||||
|
* @return Whether the pokemon can be added to the party or not
|
||||||
|
*/
|
||||||
|
applyPokemonAddToParty(_pokemon: EnemyPokemon): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for POKEMON_FUSION. Derived classes should alter this.
|
||||||
|
* @param _pokemon - The pokemon being checked
|
||||||
|
* @returns Whether the selected pokemon is allowed to fuse or not
|
||||||
|
*/
|
||||||
|
applyPokemonFusion(_pokemon: PlayerPokemon): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for POKEMON_MOVE. Derived classes should alter this.
|
||||||
|
* @param _moveId - The move being checked
|
||||||
|
* @returns Whether the move can be used or not
|
||||||
|
*/
|
||||||
|
applyPokemonMove(_moveId: MoveId): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for SHOP_ITEM. Derived classes should alter this.
|
||||||
|
* @param _shopItem - The item being checked
|
||||||
|
* @returns Whether the item should be added to the shop or not
|
||||||
|
*/
|
||||||
|
applyShopItem(_shopItem: ModifierTypeOption | null): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for WAVE_REWARD. Derived classes should alter this.
|
||||||
|
* @param _reward - The reward being checked
|
||||||
|
* @returns Whether the reward should be added to the reward options or not
|
||||||
|
*/
|
||||||
|
applyWaveReward(_reward: ModifierTypeOption | null): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An apply function for PREVENT_REVIVE. Derived classes should alter this.
|
||||||
|
* @returns Whether fainting is a permanent status or not
|
||||||
|
*/
|
||||||
|
applyPreventRevive(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChallengeCondition = (data: GameData) => boolean;
|
type ChallengeCondition = (data: GameData) => boolean;
|
||||||
@ -889,6 +959,89 @@ export class LowerStarterPointsChallenge extends Challenge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a No Support challenge
|
||||||
|
*/
|
||||||
|
export class NoSupportChallenge extends Challenge {
|
||||||
|
// 1 is no_heal
|
||||||
|
// 2 is no_shop
|
||||||
|
// 3 is both
|
||||||
|
constructor() {
|
||||||
|
super(Challenges.NO_SUPPORT, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyPartyHeal(): boolean {
|
||||||
|
return this.value === 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyShop(): boolean {
|
||||||
|
return this.value === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static override loadChallenge(source: NoSupportChallenge | any): NoSupportChallenge {
|
||||||
|
const newChallenge = new NoSupportChallenge();
|
||||||
|
newChallenge.value = source.value;
|
||||||
|
newChallenge.severity = source.severity;
|
||||||
|
return newChallenge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a Limited Catch challenge
|
||||||
|
*/
|
||||||
|
export class LimitedCatchChallenge extends Challenge {
|
||||||
|
constructor() {
|
||||||
|
super(Challenges.LIMITED_CATCH, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyPokemonAddToParty(pokemon: EnemyPokemon): boolean {
|
||||||
|
return pokemon.metWave % 10 === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static override loadChallenge(source: LimitedCatchChallenge | any): LimitedCatchChallenge {
|
||||||
|
const newChallenge = new LimitedCatchChallenge();
|
||||||
|
newChallenge.value = source.value;
|
||||||
|
newChallenge.severity = source.severity;
|
||||||
|
return newChallenge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a Permanent Faint challenge
|
||||||
|
*/
|
||||||
|
export class PermanentFaintChallenge extends Challenge {
|
||||||
|
constructor() {
|
||||||
|
super(Challenges.PERMANENT_FAINT, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyPokemonFusion(pokemon: PlayerPokemon): boolean {
|
||||||
|
return !pokemon.isFainted();
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyShopItem(shopItem: ModifierTypeOption | null): boolean {
|
||||||
|
return shopItem?.type.group !== "revive";
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyWaveReward(reward: ModifierTypeOption | null): boolean {
|
||||||
|
return this.applyShopItem(reward);
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyPokemonMove(moveId: MoveId) {
|
||||||
|
return moveId !== MoveId.REVIVAL_BLESSING;
|
||||||
|
}
|
||||||
|
|
||||||
|
override applyPreventRevive(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static override loadChallenge(source: PermanentFaintChallenge | any): PermanentFaintChallenge {
|
||||||
|
const newChallenge = new PermanentFaintChallenge();
|
||||||
|
newChallenge.value = source.value;
|
||||||
|
newChallenge.severity = source.severity;
|
||||||
|
return newChallenge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply all challenges that modify starter choice.
|
* Apply all challenges that modify starter choice.
|
||||||
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_CHOICE
|
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_CHOICE
|
||||||
@ -1041,6 +1194,66 @@ export function applyChallenges(
|
|||||||
|
|
||||||
export function applyChallenges(challengeType: ChallengeType.FLIP_STAT, pokemon: Pokemon, baseStats: number[]): boolean;
|
export function applyChallenges(challengeType: ChallengeType.FLIP_STAT, pokemon: Pokemon, baseStats: number[]): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that conditionally enable or disable automatic party healing during biome transitions
|
||||||
|
* @param challengeType - {@linkcode ChallengeType.PARTY_HEAL}
|
||||||
|
* @returns Whether party healing is enabled or not
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.PARTY_HEAL): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that conditionally enable or disable the shop
|
||||||
|
* @returns Whether the shop is or is not available after a wave
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.SHOP): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that validate whether a pokemon can be added to the player's party or not
|
||||||
|
* @param challengeType - {@linkcode ChallengeType.POKEMON_ADD_TO_PARTY}
|
||||||
|
* @param pokemon - The pokemon being caught
|
||||||
|
* @return Whether the pokemon can be added to the party or not
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.POKEMON_ADD_TO_PARTY, pokemon: EnemyPokemon): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that validate whether a pokemon is allowed to fuse or not
|
||||||
|
* @param challengeType - {@linkcode ChallengeType.POKEMON_FUSION}
|
||||||
|
* @param pokemon - The pokemon being checked
|
||||||
|
* @returns Whether the selected pokemon is allowed to fuse or not
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.POKEMON_FUSION, pokemon: PlayerPokemon): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that validate whether particular moves can or cannot be used
|
||||||
|
* @param challengeType - {@linkcode ChallengeType.POKEMON_MOVE}
|
||||||
|
* @param moveId - The move being checked
|
||||||
|
* @returns Whether the move can be used or not
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.POKEMON_MOVE, moveId: MoveId): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that validate whether particular items are or are not sold in the shop
|
||||||
|
* @param challengeType - {@linkcode ChallengeType.SHOP_ITEM}
|
||||||
|
* @param shopItem - The item being checked
|
||||||
|
* @returns Whether the item should be added to the shop or not
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.SHOP_ITEM, shopItem: ModifierTypeOption | null): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that validate whether particular items will be given as a reward after a wave
|
||||||
|
* @param challengeType - {@linkcode ChallengeType.WAVE_REWARD}
|
||||||
|
* @param reward - The reward being checked
|
||||||
|
* @returns Whether the reward should be added to the reward options or not
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.WAVE_REWARD, reward: ModifierTypeOption | null): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all challenges that prevent recovery from fainting
|
||||||
|
* @param challengeType - {@linkcode ChallengeType.PREVENT_REVIVE}
|
||||||
|
* @returns Whether fainting is a permanent status or not
|
||||||
|
*/
|
||||||
|
export function applyChallenges(challengeType: ChallengeType.PREVENT_REVIVE): boolean;
|
||||||
|
|
||||||
export function applyChallenges(challengeType: ChallengeType, ...args: any[]): boolean {
|
export function applyChallenges(challengeType: ChallengeType, ...args: any[]): boolean {
|
||||||
let ret = false;
|
let ret = false;
|
||||||
globalScene.gameMode.challenges.forEach(c => {
|
globalScene.gameMode.challenges.forEach(c => {
|
||||||
@ -1088,6 +1301,30 @@ export function applyChallenges(challengeType: ChallengeType, ...args: any[]): b
|
|||||||
case ChallengeType.FLIP_STAT:
|
case ChallengeType.FLIP_STAT:
|
||||||
ret ||= c.applyFlipStat(args[0], args[1]);
|
ret ||= c.applyFlipStat(args[0], args[1]);
|
||||||
break;
|
break;
|
||||||
|
case ChallengeType.PARTY_HEAL:
|
||||||
|
ret ||= c.applyPartyHeal();
|
||||||
|
break;
|
||||||
|
case ChallengeType.SHOP:
|
||||||
|
ret ||= c.applyShop();
|
||||||
|
break;
|
||||||
|
case ChallengeType.POKEMON_ADD_TO_PARTY:
|
||||||
|
ret ||= c.applyPokemonAddToParty(args[0]);
|
||||||
|
break;
|
||||||
|
case ChallengeType.POKEMON_FUSION:
|
||||||
|
ret ||= c.applyPokemonFusion(args[0]);
|
||||||
|
break;
|
||||||
|
case ChallengeType.POKEMON_MOVE:
|
||||||
|
ret ||= c.applyPokemonMove(args[0]);
|
||||||
|
break;
|
||||||
|
case ChallengeType.SHOP_ITEM:
|
||||||
|
ret ||= c.applyShopItem(args[0]);
|
||||||
|
break;
|
||||||
|
case ChallengeType.WAVE_REWARD:
|
||||||
|
ret ||= c.applyWaveReward(args[0]);
|
||||||
|
break;
|
||||||
|
case ChallengeType.PREVENT_REVIVE:
|
||||||
|
ret ||= c.applyPreventRevive();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1115,6 +1352,12 @@ export function copyChallenge(source: Challenge | any): Challenge {
|
|||||||
return InverseBattleChallenge.loadChallenge(source);
|
return InverseBattleChallenge.loadChallenge(source);
|
||||||
case Challenges.FLIP_STAT:
|
case Challenges.FLIP_STAT:
|
||||||
return FlipStatChallenge.loadChallenge(source);
|
return FlipStatChallenge.loadChallenge(source);
|
||||||
|
case Challenges.LIMITED_CATCH:
|
||||||
|
return LimitedCatchChallenge.loadChallenge(source);
|
||||||
|
case Challenges.NO_SUPPORT:
|
||||||
|
return NoSupportChallenge.loadChallenge(source);
|
||||||
|
case Challenges.PERMANENT_FAINT:
|
||||||
|
return PermanentFaintChallenge.loadChallenge(source);
|
||||||
}
|
}
|
||||||
throw new Error("Unknown challenge copied");
|
throw new Error("Unknown challenge copied");
|
||||||
}
|
}
|
||||||
@ -1128,6 +1371,9 @@ export function initChallenges() {
|
|||||||
new FreshStartChallenge(),
|
new FreshStartChallenge(),
|
||||||
new InverseBattleChallenge(),
|
new InverseBattleChallenge(),
|
||||||
new FlipStatChallenge(),
|
new FlipStatChallenge(),
|
||||||
|
new LimitedCatchChallenge(),
|
||||||
|
new NoSupportChallenge(),
|
||||||
|
new PermanentFaintChallenge(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
import { allMoves } from "#data/data-lists";
|
import { allMoves } from "#data/data-lists";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import type { MoveId } from "#enums/move-id";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import type { Move } from "#moves/move";
|
import type { Move } from "#moves/move";
|
||||||
@ -46,15 +48,12 @@ export class PokemonMove {
|
|||||||
*/
|
*/
|
||||||
isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean {
|
isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean {
|
||||||
// TODO: Add Sky Drop's 1 turn stall
|
// TODO: Add Sky Drop's 1 turn stall
|
||||||
if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)) {
|
const isBattleRestricted = this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon);
|
||||||
return false;
|
const hasPp = ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1;
|
||||||
}
|
const isNotChallengeRestricted = !pokemon.isPlayer() || applyChallenges(ChallengeType.POKEMON_MOVE, this.moveId);
|
||||||
|
const isUnimplemented = this.getMove().name.endsWith(" (N)");
|
||||||
|
|
||||||
if (this.getMove().name.endsWith(" (N)")) {
|
return !isBattleRestricted && hasPp && isNotChallengeRestricted && !isUnimplemented;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getMove(): Move {
|
getMove(): Move {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { speciesStarterCosts } from "#balance/starters";
|
import { speciesStarterCosts } from "#balance/starters";
|
||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
import { modifierTypes } from "#data/data-lists";
|
import { modifierTypes } from "#data/data-lists";
|
||||||
import { Gender } from "#data/gender";
|
import { Gender } from "#data/gender";
|
||||||
import {
|
import {
|
||||||
@ -13,6 +14,7 @@ import { CustomPokemonData } from "#data/pokemon-data";
|
|||||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
import { getStatusEffectCatchRateMultiplier } from "#data/status-effect";
|
import { getStatusEffectCatchRateMultiplier } from "#data/status-effect";
|
||||||
import type { AbilityId } from "#enums/ability-id";
|
import type { AbilityId } from "#enums/ability-id";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
import type { PokemonType } from "#enums/pokemon-type";
|
import type { PokemonType } from "#enums/pokemon-type";
|
||||||
@ -706,6 +708,12 @@ export async function catchPokemon(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
|
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
|
||||||
|
// TODO: Address ME edge cases (Safari Zone, etc.)
|
||||||
|
if (!applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon)) {
|
||||||
|
removePokemon();
|
||||||
|
end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (globalScene.getPlayerParty().length === 6) {
|
if (globalScene.getPlayerParty().length === 6) {
|
||||||
const promptRelease = () => {
|
const promptRelease = () => {
|
||||||
globalScene.ui.showText(
|
globalScene.ui.showText(
|
||||||
|
@ -65,5 +65,45 @@ export enum ChallengeType {
|
|||||||
/**
|
/**
|
||||||
* Modifies what the pokemon stats for Flip Stat Mode.
|
* Modifies what the pokemon stats for Flip Stat Mode.
|
||||||
*/
|
*/
|
||||||
FLIP_STAT
|
FLIP_STAT,
|
||||||
|
/**
|
||||||
|
* Challenges which conditionally enable or disable automatic party healing during biome transitions
|
||||||
|
* @see {@linkcode Challenge.applyPartyHealAvailability}
|
||||||
|
*/
|
||||||
|
PARTY_HEAL,
|
||||||
|
/**
|
||||||
|
* Challenges which conditionally enable or disable the shop
|
||||||
|
* @see {@linkcode Challenge.applyShopAvailability}
|
||||||
|
*/
|
||||||
|
SHOP,
|
||||||
|
/**
|
||||||
|
* Challenges which validate whether a pokemon can be added to the player's party or not
|
||||||
|
* @see {@linkcode Challenge.applyCatchAvailability}
|
||||||
|
*/
|
||||||
|
POKEMON_ADD_TO_PARTY,
|
||||||
|
/**
|
||||||
|
* Challenges which validate whether a pokemon is allowed to fuse or not
|
||||||
|
* @see {@linkcode Challenge.applyFusionAvailability}
|
||||||
|
*/
|
||||||
|
POKEMON_FUSION,
|
||||||
|
/**
|
||||||
|
* Challenges which validate whether particular moves can or cannot be used
|
||||||
|
* @see {@linkcode Challenge.applyMoveAvailability}
|
||||||
|
*/
|
||||||
|
POKEMON_MOVE,
|
||||||
|
/**
|
||||||
|
* Challenges which validate whether particular items are or are not sold in the shop
|
||||||
|
* @see {@linkcode Challenge.applyShopItems}
|
||||||
|
*/
|
||||||
|
SHOP_ITEM,
|
||||||
|
/**
|
||||||
|
* Challenges which validate whether particular items will be given as a reward after a wave
|
||||||
|
* @see {@linkcode Challenge.applyWaveRewards}
|
||||||
|
*/
|
||||||
|
WAVE_REWARD,
|
||||||
|
/**
|
||||||
|
* Challenges which prevent recovery from fainting
|
||||||
|
* @see {@linkcode Challenge.applyPermanentFaint}
|
||||||
|
*/
|
||||||
|
PREVENT_REVIVE,
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,7 @@ export enum Challenges {
|
|||||||
FRESH_START,
|
FRESH_START,
|
||||||
INVERSE_BATTLE,
|
INVERSE_BATTLE,
|
||||||
FLIP_STAT,
|
FLIP_STAT,
|
||||||
|
LIMITED_CATCH,
|
||||||
|
NO_SUPPORT,
|
||||||
|
PERMANENT_FAINT,
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,7 @@ import { FixedBattleConfig } from "#app/battle";
|
|||||||
import { CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
import { CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import type { Challenge } from "#data/challenge";
|
import { allChallenges, applyChallenges, type Challenge, copyChallenge } from "#data/challenge";
|
||||||
import { allChallenges, applyChallenges, copyChallenge } from "#data/challenge";
|
|
||||||
import { getDailyStartingBiome } from "#data/daily-run";
|
import { getDailyStartingBiome } from "#data/daily-run";
|
||||||
import { allSpecies } from "#data/data-lists";
|
import { allSpecies } from "#data/data-lists";
|
||||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
@ -311,6 +310,14 @@ export class GameMode implements GameModeConfig {
|
|||||||
return this.battleConfig[waveIndex];
|
return this.battleConfig[waveIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the game mode has the shop enabled or not
|
||||||
|
* @returns Whether the shop is available or not
|
||||||
|
*/
|
||||||
|
getShopAvailability(): boolean {
|
||||||
|
return !this.hasNoShop && this.modeId === GameModes.CHALLENGE && applyChallenges(ChallengeType.SHOP);
|
||||||
|
}
|
||||||
|
|
||||||
getClearScoreBonus(): number {
|
getClearScoreBonus(): number {
|
||||||
switch (this.modeId) {
|
switch (this.modeId) {
|
||||||
case GameModes.CLASSIC:
|
case GameModes.CLASSIC:
|
||||||
|
@ -6,6 +6,7 @@ import Overrides from "#app/overrides";
|
|||||||
import { EvolutionItem, pokemonEvolutions } from "#balance/pokemon-evolutions";
|
import { EvolutionItem, pokemonEvolutions } from "#balance/pokemon-evolutions";
|
||||||
import { tmPoolTiers, tmSpecies } from "#balance/tms";
|
import { tmPoolTiers, tmSpecies } from "#balance/tms";
|
||||||
import { getBerryEffectDescription, getBerryName } from "#data/berry";
|
import { getBerryEffectDescription, getBerryName } from "#data/berry";
|
||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
import { allMoves, modifierTypes } from "#data/data-lists";
|
import { allMoves, modifierTypes } from "#data/data-lists";
|
||||||
import { SpeciesFormChangeItemTrigger } from "#data/form-change-triggers";
|
import { SpeciesFormChangeItemTrigger } from "#data/form-change-triggers";
|
||||||
import { getNatureName, getNatureStatMultiplier } from "#data/nature";
|
import { getNatureName, getNatureStatMultiplier } from "#data/nature";
|
||||||
@ -14,6 +15,7 @@ import { pokemonFormChanges, SpeciesFormChangeCondition } from "#data/pokemon-fo
|
|||||||
import { getStatusEffectDescriptor } from "#data/status-effect";
|
import { getStatusEffectDescriptor } from "#data/status-effect";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import { FormChangeItem } from "#enums/form-change-item";
|
import { FormChangeItem } from "#enums/form-change-item";
|
||||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||||
import { ModifierTier } from "#enums/modifier-tier";
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
@ -533,7 +535,7 @@ export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.selectFilter = (pokemon: PlayerPokemon) => {
|
this.selectFilter = (pokemon: PlayerPokemon) => {
|
||||||
if (pokemon.hp) {
|
if (pokemon.hp || applyChallenges(ChallengeType.PREVENT_REVIVE)) {
|
||||||
return PartyUiHandler.NoEffectMessage;
|
return PartyUiHandler.NoEffectMessage;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -1262,7 +1264,7 @@ export class FusePokemonModifierType extends PokemonModifierType {
|
|||||||
iconImage,
|
iconImage,
|
||||||
(_type, args) => new FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id),
|
(_type, args) => new FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id),
|
||||||
(pokemon: PlayerPokemon) => {
|
(pokemon: PlayerPokemon) => {
|
||||||
if (pokemon.isFusion()) {
|
if (pokemon.isFusion() || !applyChallenges(ChallengeType.POKEMON_FUSION, pokemon)) {
|
||||||
return PartyUiHandler.NoEffectMessage;
|
return PartyUiHandler.NoEffectMessage;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -2574,11 +2576,14 @@ function getModifierTypeOptionWithRetry(
|
|||||||
): ModifierTypeOption {
|
): ModifierTypeOption {
|
||||||
allowLuckUpgrades = allowLuckUpgrades ?? true;
|
allowLuckUpgrades = allowLuckUpgrades ?? true;
|
||||||
let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, tier, undefined, 0, allowLuckUpgrades);
|
let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, tier, undefined, 0, allowLuckUpgrades);
|
||||||
|
let candidateValidity = applyChallenges(ChallengeType.WAVE_REWARD, candidate);
|
||||||
let r = 0;
|
let r = 0;
|
||||||
while (
|
while (
|
||||||
existingOptions.length &&
|
(existingOptions.length &&
|
||||||
++r < retryCount &&
|
++r < retryCount &&
|
||||||
existingOptions.filter(o => o.type.name === candidate?.type.name || o.type.group === candidate?.type.group).length
|
existingOptions.filter(o => o.type.name === candidate?.type.name || o.type.group === candidate?.type.group)
|
||||||
|
.length) ||
|
||||||
|
!candidateValidity
|
||||||
) {
|
) {
|
||||||
candidate = getNewModifierTypeOption(
|
candidate = getNewModifierTypeOption(
|
||||||
party,
|
party,
|
||||||
@ -2588,6 +2593,7 @@ function getModifierTypeOptionWithRetry(
|
|||||||
0,
|
0,
|
||||||
allowLuckUpgrades,
|
allowLuckUpgrades,
|
||||||
);
|
);
|
||||||
|
candidateValidity = applyChallenges(ChallengeType.WAVE_REWARD, candidate);
|
||||||
}
|
}
|
||||||
return candidate!;
|
return candidate!;
|
||||||
}
|
}
|
||||||
@ -2648,7 +2654,11 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: number, baseC
|
|||||||
[new ModifierTypeOption(modifierTypeInitObj.FULL_RESTORE(), 0, baseCost * 2.25)],
|
[new ModifierTypeOption(modifierTypeInitObj.FULL_RESTORE(), 0, baseCost * 2.25)],
|
||||||
[new ModifierTypeOption(modifierTypeInitObj.SACRED_ASH(), 0, baseCost * 10)],
|
[new ModifierTypeOption(modifierTypeInitObj.SACRED_ASH(), 0, baseCost * 10)],
|
||||||
];
|
];
|
||||||
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
|
||||||
|
return options
|
||||||
|
.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30))
|
||||||
|
.flat()
|
||||||
|
.filter(shopItem => applyChallenges(ChallengeType.SHOP_ITEM, shopItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnemyBuffModifierForWave(
|
export function getEnemyBuffModifierForWave(
|
||||||
|
@ -2,6 +2,7 @@ import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { SubstituteTag } from "#data/battler-tags";
|
import { SubstituteTag } from "#data/battler-tags";
|
||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
import { Gender } from "#data/gender";
|
import { Gender } from "#data/gender";
|
||||||
import {
|
import {
|
||||||
doPokeballBounceAnim,
|
doPokeballBounceAnim,
|
||||||
@ -12,6 +13,7 @@ import {
|
|||||||
} from "#data/pokeball";
|
} from "#data/pokeball";
|
||||||
import { getStatusEffectCatchRateMultiplier } from "#data/status-effect";
|
import { getStatusEffectCatchRateMultiplier } from "#data/status-effect";
|
||||||
import { BattlerIndex } from "#enums/battler-index";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
@ -287,6 +289,11 @@ export class AttemptCapturePhase extends PokemonPhase {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
|
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
|
||||||
|
if (!applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon)) {
|
||||||
|
removePokemon();
|
||||||
|
end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (globalScene.getPlayerParty().length === PLAYER_PARTY_MAX_SIZE) {
|
if (globalScene.getPlayerParty().length === PLAYER_PARTY_MAX_SIZE) {
|
||||||
const promptRelease = () => {
|
const promptRelease = () => {
|
||||||
globalScene.ui.showText(
|
globalScene.ui.showText(
|
||||||
|
@ -4,12 +4,14 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
|||||||
import { speciesStarterCosts } from "#balance/starters";
|
import { speciesStarterCosts } from "#balance/starters";
|
||||||
import type { EncoreTag } from "#data/battler-tags";
|
import type { EncoreTag } from "#data/battler-tags";
|
||||||
import { TrappedTag } from "#data/battler-tags";
|
import { TrappedTag } from "#data/battler-tags";
|
||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { ArenaTagSide } from "#enums/arena-tag-side";
|
import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
import { BattleType } from "#enums/battle-type";
|
import { BattleType } from "#enums/battle-type";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { BiomeId } from "#enums/biome-id";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import { Command } from "#enums/command";
|
import { Command } from "#enums/command";
|
||||||
import { FieldPosition } from "#enums/field-position";
|
import { FieldPosition } from "#enums/field-position";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
@ -220,18 +222,31 @@ export class CommandPhase extends FieldPhase {
|
|||||||
const move = playerPokemon.getMoveset()[cursor];
|
const move = playerPokemon.getMoveset()[cursor];
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||||
|
|
||||||
// Decides between a Disabled, Not Implemented, or No PP translation message
|
// Set the translation key for why the move cannot be selected. The reasons can be:
|
||||||
const errorMessage = playerPokemon.isMoveRestricted(move.moveId, playerPokemon)
|
// - If the move has been restricted in battle (e.g., Disable).
|
||||||
? playerPokemon
|
// - If the move has no more PP.
|
||||||
|
// - If the move is restricted by a challenge.
|
||||||
|
// - If the move is not implemented
|
||||||
|
let cannotUseKey: string;
|
||||||
|
if (playerPokemon.isMoveRestricted(move.moveId, playerPokemon)) {
|
||||||
|
cannotUseKey = playerPokemon
|
||||||
.getRestrictingTag(move.moveId, playerPokemon)!
|
.getRestrictingTag(move.moveId, playerPokemon)!
|
||||||
.selectionDeniedText(playerPokemon, move.moveId)
|
.selectionDeniedText(playerPokemon, move.moveId);
|
||||||
: move.getName().endsWith(" (N)")
|
} else if (move.getPpRatio() === 0) {
|
||||||
? "battle:moveNotImplemented"
|
cannotUseKey = "battle:moveNoPP";
|
||||||
: "battle:moveNoPP";
|
} else if (!applyChallenges(ChallengeType.POKEMON_MOVE, move.moveId)) {
|
||||||
|
cannotUseKey = "battle:moveCannotUseChallenge";
|
||||||
|
} else if (move.getName().endsWith(" (N)")) {
|
||||||
|
cannotUseKey = "battle:moveNotImplemented";
|
||||||
|
} else {
|
||||||
|
// TODO: Consider a message that signals a being unusable for an unknown reason
|
||||||
|
cannotUseKey = "";
|
||||||
|
}
|
||||||
|
|
||||||
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
||||||
|
|
||||||
globalScene.ui.showText(
|
globalScene.ui.showText(
|
||||||
i18next.t(errorMessage, { moveName: moveName }),
|
i18next.t(cannotUseKey, { moveName: moveName }),
|
||||||
null,
|
null,
|
||||||
() => {
|
() => {
|
||||||
globalScene.ui.clearText();
|
globalScene.ui.clearText();
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import { BattlePhase } from "#phases/battle-phase";
|
import { BattlePhase } from "#phases/battle-phase";
|
||||||
import { fixedInt } from "#utils/common";
|
import { fixedInt } from "#utils/common";
|
||||||
|
|
||||||
@ -20,7 +22,9 @@ export class PartyHealPhase extends BattlePhase {
|
|||||||
globalScene.fadeOutBgm(1000, false);
|
globalScene.fadeOutBgm(1000, false);
|
||||||
}
|
}
|
||||||
globalScene.ui.fadeOut(1000).then(() => {
|
globalScene.ui.fadeOut(1000).then(() => {
|
||||||
|
const preventRevive = applyChallenges(ChallengeType.PREVENT_REVIVE);
|
||||||
for (const pokemon of globalScene.getPlayerParty()) {
|
for (const pokemon of globalScene.getPlayerParty()) {
|
||||||
|
if (!(pokemon.isFainted() && preventRevive)) {
|
||||||
pokemon.hp = pokemon.getMaxHp();
|
pokemon.hp = pokemon.getMaxHp();
|
||||||
pokemon.resetStatus(true, false, false, true);
|
pokemon.resetStatus(true, false, false, true);
|
||||||
for (const move of pokemon.moveset) {
|
for (const move of pokemon.moveset) {
|
||||||
@ -28,6 +32,7 @@ export class PartyHealPhase extends BattlePhase {
|
|||||||
}
|
}
|
||||||
pokemon.updateInfo(true);
|
pokemon.updateInfo(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const healSong = globalScene.playSoundWithoutBgm("heal");
|
const healSong = globalScene.playSoundWithoutBgm("heal");
|
||||||
globalScene.time.delayedCall(fixedInt(healSong.totalDuration * 1000), () => {
|
globalScene.time.delayedCall(fixedInt(healSong.totalDuration * 1000), () => {
|
||||||
healSong.destroy();
|
healSong.destroy();
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { biomeLinks, getBiomeName } from "#balance/biomes";
|
import { biomeLinks, getBiomeName } from "#balance/biomes";
|
||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
import { BiomeId } from "#enums/biome-id";
|
import { BiomeId } from "#enums/biome-id";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { MapModifier, MoneyInterestModifier } from "#modifiers/modifier";
|
import { MapModifier, MoneyInterestModifier } from "#modifiers/modifier";
|
||||||
import { BattlePhase } from "#phases/battle-phase";
|
import { BattlePhase } from "#phases/battle-phase";
|
||||||
@ -20,8 +22,10 @@ export class SelectBiomePhase extends BattlePhase {
|
|||||||
const setNextBiome = (nextBiome: BiomeId) => {
|
const setNextBiome = (nextBiome: BiomeId) => {
|
||||||
if (nextWaveIndex % 10 === 1) {
|
if (nextWaveIndex % 10 === 1) {
|
||||||
globalScene.applyModifiers(MoneyInterestModifier, true);
|
globalScene.applyModifiers(MoneyInterestModifier, true);
|
||||||
|
if (applyChallenges(ChallengeType.PARTY_HEAL)) {
|
||||||
globalScene.phaseManager.unshiftNew("PartyHealPhase", false);
|
globalScene.phaseManager.unshiftNew("PartyHealPhase", false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
globalScene.phaseManager.unshiftNew("SwitchBiomePhase", nextBiome);
|
globalScene.phaseManager.unshiftNew("SwitchBiomePhase", nextBiome);
|
||||||
this.end();
|
this.end();
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { timedEventManager } from "#app/global-event-manager";
|
import { timedEventManager } from "#app/global-event-manager";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { applyChallenges } from "#data/challenge";
|
||||||
import { modifierTypes } from "#data/data-lists";
|
import { modifierTypes } from "#data/data-lists";
|
||||||
import { BattleType } from "#enums/battle-type";
|
import { BattleType } from "#enums/battle-type";
|
||||||
import type { BattlerIndex } from "#enums/battler-index";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||||
import type { CustomModifierSettings } from "#modifiers/modifier-type";
|
import type { CustomModifierSettings } from "#modifiers/modifier-type";
|
||||||
import { handleMysteryEncounterVictory } from "#mystery-encounters/encounter-phase-utils";
|
import { handleMysteryEncounterVictory } from "#mystery-encounters/encounter-phase-utils";
|
||||||
@ -63,7 +65,7 @@ export class VictoryPhase extends PokemonPhase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (globalScene.currentBattle.waveIndex % 10) {
|
if (globalScene.currentBattle.waveIndex % 10 !== 0 || !applyChallenges(ChallengeType.PARTY_HEAL)) {
|
||||||
globalScene.phaseManager.pushNew(
|
globalScene.phaseManager.pushNew(
|
||||||
"SelectModifierPhase",
|
"SelectModifierPhase",
|
||||||
undefined,
|
undefined,
|
||||||
|
@ -209,10 +209,10 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||||||
this.updateRerollCostText();
|
this.updateRerollCostText();
|
||||||
|
|
||||||
const typeOptions = args[1] as ModifierTypeOption[];
|
const typeOptions = args[1] as ModifierTypeOption[];
|
||||||
const removeHealShop = globalScene.gameMode.hasNoShop;
|
const hasShop = globalScene.gameMode.getShopAvailability();
|
||||||
const baseShopCost = new NumberHolder(globalScene.getWaveMoneyAmount(1));
|
const baseShopCost = new NumberHolder(globalScene.getWaveMoneyAmount(1));
|
||||||
globalScene.applyModifier(HealShopCostModifier, true, baseShopCost);
|
globalScene.applyModifier(HealShopCostModifier, true, baseShopCost);
|
||||||
const shopTypeOptions = !removeHealShop
|
const shopTypeOptions = hasShop
|
||||||
? getPlayerShopModifierTypeOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value)
|
? getPlayerShopModifierTypeOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value)
|
||||||
: [];
|
: [];
|
||||||
const optionsYOffset =
|
const optionsYOffset =
|
||||||
@ -370,7 +370,7 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||||||
if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) {
|
if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) {
|
||||||
this.setRowCursor(0);
|
this.setRowCursor(0);
|
||||||
this.setCursor(2);
|
this.setCursor(2);
|
||||||
} else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && globalScene.gameMode.hasNoShop) {
|
} else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && !hasShop) {
|
||||||
this.setRowCursor(ShopCursorTarget.REWARDS);
|
this.setRowCursor(ShopCursorTarget.REWARDS);
|
||||||
this.setCursor(0);
|
this.setCursor(0);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user