mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-20 16:42:45 +02:00
Merge b9cc1843d9
into 4b70fab608
This commit is contained in:
commit
feafb52ab0
@ -20,12 +20,14 @@ import { Challenges } from "#enums/challenges";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import { Nature } from "#enums/nature";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { TypeColor, TypeShadow } from "#enums/color";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { pokemonFormChanges } from "./pokemon-forms";
|
||||
import { pokemonEvolutions } from "./balance/pokemon-evolutions";
|
||||
import type { ModifierTypeOption } from "#app/modifier/modifier-type";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
import type { MoveSourceType } from "#enums/move-source-type";
|
||||
|
||||
@ -345,6 +347,84 @@ export abstract class Challenge {
|
||||
applyFlipStat(_pokemon: Pokemon, _baseStats: number[]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for NO_AUTO_HEAL challenges. Derived classes should alter this.
|
||||
* @param _applyHealPhase {@link BooleanHolder} Whether it should apply the heal phase.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyNoHealPhase(_applyHealPhase: BooleanHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for PREVENT_REVIVE. Derived classes should alter this.
|
||||
* @param _canBeRevived {@link BooleanHolder} Whether it should revive the fainted Pokemon.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyRevivePrevention(_canBeRevived: BooleanHolder): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for RANDOM_ITEM_BLACKLIST. Derived classes should alter this.
|
||||
* @param _randomItem {@link ModifierTypeOption} The random item in question.
|
||||
* @param _isValid {@link BooleanHolder} Whether it should load the random item.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyRandomItemBlacklist(_randomItem: ModifierTypeOption | null, _isValid: BooleanHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for SHOP_ITEM_BLACKLIST. Derived classes should alter this.
|
||||
* @param _shopItem {@link ModifierTypeOption} The shop item in question.
|
||||
* @param _isValid {@link BooleanHolder} Whether the shop should have the item.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyShopItemBlacklist(_shopItem: ModifierTypeOption | null, _isValid: BooleanHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for MOVE_BLACKLIST. Derived classes should alter this.
|
||||
* @param _move {@link PokemonMove} The move in question.
|
||||
* @param _isValid {@link BooleanHolder} Whether the move should be allowed.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyMoveBlacklist(_move: PokemonMove, _isValid: BooleanHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for DELETE_POKEMON. Derived classes should alter this.
|
||||
* @param _canStay {@link BooleanHolder} Whether the pokemon can stay in team after death.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyDeletePokemon(_canStay: BooleanHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for ADD_POKEMON_TO_PARTY. Derived classes should alter this.
|
||||
* @param _waveIndex {@link BooleanHolder} The current wave.
|
||||
* @param _canAddToParty {@link BooleanHolder} Whether the pokemon can be caught.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyAddPokemonToParty(_waveIndex: number, _canAddToParty: BooleanHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for SHOULD_FUSE. Derived classes should alter this.
|
||||
* @param _pokemon {@link Pokemon} The first chosen pokemon for fusion.
|
||||
* @param _pokemonTofuse {@link Pokemon} The second chosen pokemon for fusion.
|
||||
* @param _canFuse {@link BooleanHolder} Whether the pokemons can fuse.
|
||||
* @returns {@link boolean} if this function did anything.
|
||||
*/
|
||||
applyShouldFuse(_pokemon: Pokemon, _pokemonTofuse: Pokemon, _canFuse: BooleanHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
type ChallengeCondition = (data: GameData) => boolean;
|
||||
@ -889,6 +969,123 @@ export class LowerStarterPointsChallenge extends Challenge {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Challenge stops pokemon from healing every 10th wave
|
||||
*/
|
||||
export class NoFreeHealsChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.NO_AUTO_HEAL, 1);
|
||||
}
|
||||
|
||||
applyNoHealPhase(applyHealPhase: BooleanHolder): boolean {
|
||||
applyHealPhase.value = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static loadChallenge(source: NoFreeHealsChallenge | any): NoFreeHealsChallenge {
|
||||
const newChallenge = new NoFreeHealsChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Challenge that removes the ability to revive fallen pokemon
|
||||
*/
|
||||
export class HardcoreChallenge extends Challenge {
|
||||
private itemBlackList = [
|
||||
"modifierType:ModifierType.REVIVE",
|
||||
"modifierType:ModifierType.MAX_REVIVE",
|
||||
"modifierType:ModifierType.SACRED_ASH",
|
||||
"modifierType:ModifierType.REVIVER_SEED",
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super(Challenges.HARDCORE, 2);
|
||||
}
|
||||
|
||||
applyRandomItemBlacklist(randomItem: ModifierTypeOption, isValid: BooleanHolder): boolean {
|
||||
if (randomItem !== null) {
|
||||
isValid.value = !this.itemBlackList.includes(randomItem.type.localeKey);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
applyShopItemBlacklist(shopItem: ModifierTypeOption, isValid: BooleanHolder): boolean {
|
||||
isValid.value = !this.itemBlackList.includes(shopItem.type.localeKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
applyMoveBlacklist(move: PokemonMove, moveCanBeUsed: BooleanHolder): boolean {
|
||||
const moveBlacklist = [MoveId.REVIVAL_BLESSING];
|
||||
moveCanBeUsed.value = !moveBlacklist.includes(move.moveId);
|
||||
return true;
|
||||
}
|
||||
|
||||
applyRevivePrevention(canBeRevived: BooleanHolder): boolean {
|
||||
canBeRevived.value = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
applyDeletePokemon(canStay: BooleanHolder): boolean {
|
||||
if (this.value === 2) {
|
||||
canStay.value = false;
|
||||
} else {
|
||||
canStay.value = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override applyShouldFuse(pokemon: Pokemon, pokemonToFuse: Pokemon, canFuse: BooleanHolder): boolean {
|
||||
if (pokemon!.isFainted() || pokemonToFuse.isFainted()) {
|
||||
canFuse.value = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static override loadChallenge(source: HardcoreChallenge | any): HardcoreChallenge {
|
||||
const newChallenge = new HardcoreChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Challenge that limits the amount of caught pokemons by 1 per biome stage
|
||||
*/
|
||||
export class LimitedCatchChallenge extends Challenge {
|
||||
private mysteryEncounterBlacklist = [
|
||||
MysteryEncounterType.ABSOLUTE_AVARICE,
|
||||
MysteryEncounterType.DANCING_LESSONS,
|
||||
MysteryEncounterType.SAFARI_ZONE,
|
||||
MysteryEncounterType.THE_POKEMON_SALESMAN,
|
||||
MysteryEncounterType.UNCOMMON_BREED,
|
||||
];
|
||||
constructor() {
|
||||
super(Challenges.LIMITED_CATCH, 1);
|
||||
}
|
||||
|
||||
override applyAddPokemonToParty(waveIndex: number, canAddToParty: BooleanHolder): boolean {
|
||||
const lastMystery = globalScene.lastMysteryEncounter?.encounterType;
|
||||
if (lastMystery === undefined && !(waveIndex % 10 === 1)) {
|
||||
canAddToParty.value = false;
|
||||
}
|
||||
if (!(waveIndex % 10 === 1) && !(!this.mysteryEncounterBlacklist.includes(lastMystery!) && waveIndex % 10 === 2)) {
|
||||
canAddToParty.value = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static override loadChallenge(source: LimitedCatchChallenge | any): LimitedCatchChallenge {
|
||||
const newChallenge = new LimitedCatchChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all challenges that modify starter choice.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_CHOICE
|
||||
@ -1040,6 +1237,90 @@ export function applyChallenges(
|
||||
): boolean;
|
||||
|
||||
export function applyChallenges(challengeType: ChallengeType.FLIP_STAT, pokemon: Pokemon, baseStats: number[]): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a pokemon can be auto healed or not in wave 10m.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.NO_HEAL_PHASE
|
||||
* @param applyHealPhase {@link BooleanHolder} Whether it should apply the heal phase.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(challengeType: ChallengeType.NO_HEAL_PHASE, applyHealPhase: BooleanHolder): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a shop item should be blacklisted.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.SHOP_ITEM_BLACKLIST
|
||||
* @param shopItem {@link ModifierTypeOption} The shop item in question.
|
||||
* @param isValid {@link BooleanHolder} Whether the shop should have the item.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(
|
||||
challengeType: ChallengeType.SHOP_ITEM_BLACKLIST,
|
||||
shopItem: ModifierTypeOption | null,
|
||||
isValid: BooleanHolder,
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
* Apply all challenges that modify whether a reward item should be blacklisted.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.RANDOM_ITEM_BLACKLIST
|
||||
* @param randomItem {@link ModifierTypeOption} The random item in question.
|
||||
* @param isValid {@link BooleanHolder} Whether it should load the random item.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(
|
||||
challengeType: ChallengeType.RANDOM_ITEM_BLACKLIST,
|
||||
randomItem: ModifierTypeOption | null,
|
||||
isValid: BooleanHolder,
|
||||
): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a pokemon move should be blacklisted.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.MOVE_BLACKLIST
|
||||
* @param move {@link PokemonMove} The move in question.
|
||||
* @param isValid {@link BooleanHolder} Whether the move should be allowed.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(
|
||||
challengeType: ChallengeType.MOVE_BLACKLIST,
|
||||
move: PokemonMove,
|
||||
isValid: BooleanHolder,
|
||||
): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a pokemon should be removed from the team.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.DELETE_POKEMON
|
||||
* @param canStay {@link BooleanHolder} Whether the pokemon can stay in team after death.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(challengeType: ChallengeType.DELETE_POKEMON, canStay: BooleanHolder): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a pokemon should revive.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.PREVENT_REVIVE
|
||||
* @param canBeRevived {@link BooleanHolder} Whether it should revive the fainted Pokemon.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(challengeType: ChallengeType.PREVENT_REVIVE, canBeRevived: BooleanHolder): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a pokemon can be caught.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.ADD_POKEMON_TO_PARTY
|
||||
* @param waveIndex {@link BooleanHolder} The current wave.
|
||||
* @param canAddToParty {@link BooleanHolder} Whether the pokemon can be caught.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(
|
||||
challengeType: ChallengeType.ADD_POKEMON_TO_PARTY,
|
||||
waveIndex: number,
|
||||
canAddToParty: BooleanHolder,
|
||||
): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a pokemon can fuse.
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.SHOULD_FUSE
|
||||
* @param pokemon {@link Pokemon} The first chosen pokemon for fusion.
|
||||
* @param pokemonTofuse {@link Pokemon} The second chosen pokemon for fusion.
|
||||
* @param canFuse {@link BooleanHolder} Whether the pokemons can fuse.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(
|
||||
challengeType: ChallengeType.SHOULD_FUSE,
|
||||
pokemon: Pokemon,
|
||||
pokemonTofuse: Pokemon,
|
||||
canFuse: BooleanHolder,
|
||||
): boolean;
|
||||
|
||||
export function applyChallenges(challengeType: ChallengeType, ...args: any[]): boolean {
|
||||
let ret = false;
|
||||
@ -1088,6 +1369,30 @@ export function applyChallenges(challengeType: ChallengeType, ...args: any[]): b
|
||||
case ChallengeType.FLIP_STAT:
|
||||
ret ||= c.applyFlipStat(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.NO_HEAL_PHASE:
|
||||
ret ||= c.applyNoHealPhase(args[0]);
|
||||
break;
|
||||
case ChallengeType.SHOP_ITEM_BLACKLIST:
|
||||
ret ||= c.applyShopItemBlacklist(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.RANDOM_ITEM_BLACKLIST:
|
||||
ret ||= c.applyRandomItemBlacklist(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.MOVE_BLACKLIST:
|
||||
ret ||= c.applyMoveBlacklist(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.DELETE_POKEMON:
|
||||
ret ||= c.applyDeletePokemon(args[0]);
|
||||
break;
|
||||
case ChallengeType.PREVENT_REVIVE:
|
||||
ret ||= c.applyRevivePrevention(args[0]);
|
||||
break;
|
||||
case ChallengeType.ADD_POKEMON_TO_PARTY:
|
||||
ret ||= c.applyAddPokemonToParty(args[0], args[1]);
|
||||
break;
|
||||
case ChallengeType.SHOULD_FUSE:
|
||||
ret ||= c.applyShouldFuse(args[0], args[1], args[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1115,6 +1420,12 @@ export function copyChallenge(source: Challenge | any): Challenge {
|
||||
return InverseBattleChallenge.loadChallenge(source);
|
||||
case Challenges.FLIP_STAT:
|
||||
return FlipStatChallenge.loadChallenge(source);
|
||||
case Challenges.NO_AUTO_HEAL:
|
||||
return NoFreeHealsChallenge.loadChallenge(source);
|
||||
case Challenges.HARDCORE:
|
||||
return HardcoreChallenge.loadChallenge(source);
|
||||
case Challenges.LIMITED_CATCH:
|
||||
return LimitedCatchChallenge.loadChallenge(source);
|
||||
}
|
||||
throw new Error("Unknown challenge copied");
|
||||
}
|
||||
@ -1128,6 +1439,9 @@ export function initChallenges() {
|
||||
new FreshStartChallenge(),
|
||||
new InverseBattleChallenge(),
|
||||
new FlipStatChallenge(),
|
||||
new NoFreeHealsChallenge(),
|
||||
new LimitedCatchChallenge(),
|
||||
new HardcoreChallenge(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,9 @@ import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import type { AbilityId } from "#enums/ability-id";
|
||||
import type { PokeballType } from "#enums/pokeball";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { BooleanHolder } from "#app/utils/common";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
|
||||
/** Will give +1 level every 10 waves */
|
||||
export const STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER = 1;
|
||||
@ -703,6 +706,17 @@ export async function catchPokemon(
|
||||
});
|
||||
};
|
||||
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
|
||||
const challengeCanAddToParty = new BooleanHolder(true);
|
||||
applyChallenges(
|
||||
ChallengeType.ADD_POKEMON_TO_PARTY,
|
||||
globalScene.currentBattle.waveIndex,
|
||||
challengeCanAddToParty,
|
||||
);
|
||||
if (!challengeCanAddToParty.value) {
|
||||
removePokemon();
|
||||
end();
|
||||
return;
|
||||
}
|
||||
if (globalScene.getPlayerParty().length === 6) {
|
||||
const promptRelease = () => {
|
||||
globalScene.ui.showText(
|
||||
|
@ -65,5 +65,44 @@ export enum ChallengeType {
|
||||
/**
|
||||
* Modifies what the pokemon stats for Flip Stat Mode.
|
||||
*/
|
||||
FLIP_STAT
|
||||
FLIP_STAT,
|
||||
/**
|
||||
* Challenge that modifies if the player should auto heal every 10th wave
|
||||
*/
|
||||
NO_HEAL_PHASE,
|
||||
/**
|
||||
* Modifies if the shop item is blacklisted
|
||||
* @see {@linkcode Challenge.applyShopItemBlacklist}
|
||||
*/
|
||||
SHOP_ITEM_BLACKLIST,
|
||||
/**
|
||||
* Modifies if the random item is blacklisted
|
||||
* @see {@linkcode Challenge.applyRandomItemBlacklist}
|
||||
*/
|
||||
RANDOM_ITEM_BLACKLIST,
|
||||
/**
|
||||
* Modifies if the move is blacklisted
|
||||
* @see {@linkcode Challenge.applyMoveBlacklist}
|
||||
*/
|
||||
MOVE_BLACKLIST,
|
||||
/**
|
||||
* Modifies if pokemon are allowed to be revived from fainting
|
||||
* @see {@linkcode Challenge.applyRevivePrevention}
|
||||
*/
|
||||
PREVENT_REVIVE,
|
||||
/**
|
||||
* Modifies if pokemon are allowed to be revived from fainting
|
||||
* @see {@linkcode Challenge.applyDeletePokemon}
|
||||
*/
|
||||
DELETE_POKEMON,
|
||||
/**
|
||||
* Challenge that modifies if the player should catch pokemon on waves other than the first
|
||||
* @see {@linkcode Challenge.applyAddPokemonToParty}
|
||||
*/
|
||||
ADD_POKEMON_TO_PARTY,
|
||||
/**
|
||||
* Modifies if pokemon are allowed to fuse
|
||||
* @see {@linkcode Challenge.applyShouldFuse}
|
||||
*/
|
||||
SHOULD_FUSE,
|
||||
}
|
||||
|
@ -6,4 +6,7 @@ export enum Challenges {
|
||||
FRESH_START,
|
||||
INVERSE_BATTLE,
|
||||
FLIP_STAT,
|
||||
NO_AUTO_HEAL,
|
||||
HARDCORE,
|
||||
LIMITED_CATCH,
|
||||
}
|
||||
|
@ -3178,6 +3178,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
public trySelectMove(moveIndex: number, ignorePp?: boolean): boolean {
|
||||
const move = this.getMoveset().length > moveIndex ? this.getMoveset()[moveIndex] : null;
|
||||
if (move !== null) {
|
||||
const isValid = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.MOVE_BLACKLIST, move!, isValid);
|
||||
if (!isValid.value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return move?.isUsable(this, ignorePp) ?? false;
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,7 @@ import {
|
||||
NumberHolder,
|
||||
padInt,
|
||||
randSeedInt,
|
||||
BooleanHolder,
|
||||
} from "#app/utils/common";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
@ -128,6 +129,8 @@ import { TYPE_BOOST_ITEM_BOOST_PERCENT } from "#app/constants";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { getModifierPoolForType, getModifierType } from "#app/utils/modifier-utils";
|
||||
import type { ModifierTypeFunc, WeightedModifierTypeWeightFunc } from "#app/@types/modifier-types";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
|
||||
const outputModifierData = false;
|
||||
const useMaxWeightForOutput = false;
|
||||
@ -2613,10 +2616,14 @@ function getModifierTypeOptionWithRetry(
|
||||
allowLuckUpgrades = allowLuckUpgrades ?? true;
|
||||
let candidate = getNewModifierTypeOption(party, ModifierPoolType.PLAYER, tier, undefined, 0, allowLuckUpgrades);
|
||||
let r = 0;
|
||||
const isValidForChallenge = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.RANDOM_ITEM_BLACKLIST, candidate, isValidForChallenge);
|
||||
while (
|
||||
existingOptions.length &&
|
||||
++r < retryCount &&
|
||||
existingOptions.filter(o => o.type.name === candidate?.type.name || o.type.group === candidate?.type.group).length
|
||||
(existingOptions.length &&
|
||||
++r < retryCount &&
|
||||
existingOptions.filter(o => o.type.name === candidate?.type.name || o.type.group === candidate?.type.group)
|
||||
.length) ||
|
||||
!isValidForChallenge.value
|
||||
) {
|
||||
candidate = getNewModifierTypeOption(
|
||||
party,
|
||||
@ -2626,6 +2633,7 @@ function getModifierTypeOptionWithRetry(
|
||||
0,
|
||||
allowLuckUpgrades,
|
||||
);
|
||||
applyChallenges(ChallengeType.RANDOM_ITEM_BLACKLIST, candidate, isValidForChallenge);
|
||||
}
|
||||
return candidate!;
|
||||
}
|
||||
@ -2656,7 +2664,9 @@ export function overridePlayerModifierTypeOptions(options: ModifierTypeOption[],
|
||||
}
|
||||
|
||||
export function getPlayerShopModifierTypeOptionsForWave(waveIndex: number, baseCost: number): ModifierTypeOption[] {
|
||||
if (!(waveIndex % 10)) {
|
||||
const isHealPhaseActive = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.NO_HEAL_PHASE, isHealPhaseActive);
|
||||
if (!(waveIndex % 10) && isHealPhaseActive.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,8 @@ import { FRIENDSHIP_GAIN_FROM_RARE_CANDY } from "#app/data/balance/starters";
|
||||
import { applyAbAttrs, applyPostItemLostAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { ModifierInstanceMap, ModifierString } from "#app/@types/modifier-types";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
|
||||
export type ModifierPredicate = (modifier: Modifier) => boolean;
|
||||
|
||||
@ -2426,8 +2428,13 @@ export class FusePokemonModifier extends ConsumablePokemonModifier {
|
||||
* @returns `true` if {@linkcode FusePokemonModifier} should be applied
|
||||
*/
|
||||
override shouldApply(playerPokemon?: PlayerPokemon, playerPokemon2?: PlayerPokemon): boolean {
|
||||
const shouldFuse = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.SHOULD_FUSE, playerPokemon!, playerPokemon2!, shouldFuse);
|
||||
return (
|
||||
super.shouldApply(playerPokemon, playerPokemon2) && !!playerPokemon2 && this.fusePokemonId === playerPokemon2.id
|
||||
super.shouldApply(playerPokemon, playerPokemon2) &&
|
||||
!!playerPokemon2 &&
|
||||
this.fusePokemonId === playerPokemon2.id &&
|
||||
shouldFuse.value
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,9 @@ import { StatusEffect } from "#enums/status-effect";
|
||||
import i18next from "i18next";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { BooleanHolder } from "#app/utils/common";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
|
||||
export class AttemptCapturePhase extends PokemonPhase {
|
||||
public readonly phaseName = "AttemptCapturePhase";
|
||||
@ -285,6 +288,17 @@ export class AttemptCapturePhase extends PokemonPhase {
|
||||
});
|
||||
};
|
||||
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
|
||||
const challengeCanAddToParty = new BooleanHolder(true);
|
||||
applyChallenges(
|
||||
ChallengeType.ADD_POKEMON_TO_PARTY,
|
||||
globalScene.currentBattle.waveIndex,
|
||||
challengeCanAddToParty,
|
||||
);
|
||||
if (!challengeCanAddToParty.value) {
|
||||
removePokemon();
|
||||
end();
|
||||
return;
|
||||
}
|
||||
if (globalScene.getPlayerParty().length === PLAYER_PARTY_MAX_SIZE) {
|
||||
const promptRelease = () => {
|
||||
globalScene.ui.showText(
|
||||
|
@ -2,6 +2,9 @@ import { globalScene } from "#app/global-scene";
|
||||
import { applyPostBattleAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||
import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
import { BooleanHolder } from "#app/utils/common";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
|
||||
export class BattleEndPhase extends BattlePhase {
|
||||
public readonly phaseName = "BattleEndPhase";
|
||||
@ -67,6 +70,16 @@ export class BattleEndPhase extends BattlePhase {
|
||||
for (const pokemon of globalScene.getPokemonAllowedInBattle()) {
|
||||
applyPostBattleAbAttrs("PostBattleAbAttr", pokemon, false, this.isVictory);
|
||||
}
|
||||
const canStay = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.DELETE_POKEMON, canStay);
|
||||
if (!canStay.value) {
|
||||
const party = globalScene.getPlayerParty().slice();
|
||||
for (const pokemon of party) {
|
||||
if (pokemon.isFainted()) {
|
||||
globalScene.removePokemonFromPlayerParty(pokemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (globalScene.currentBattle.moneyScattered) {
|
||||
globalScene.currentBattle.pickUpScatteredMoney();
|
||||
|
@ -226,7 +226,9 @@ export class CommandPhase extends FieldPhase {
|
||||
.selectionDeniedText(playerPokemon, move.moveId)
|
||||
: move.getName().endsWith(" (N)")
|
||||
? "battle:moveNotImplemented"
|
||||
: "battle:moveNoPP";
|
||||
: move.getPpRatio()
|
||||
? "battle:moveDisabled"
|
||||
: "battle:moveNoPP";
|
||||
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
||||
|
||||
globalScene.ui.showText(
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { fixedInt } from "#app/utils/common";
|
||||
import { BooleanHolder, fixedInt } from "#app/utils/common";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
|
||||
export class PartyHealPhase extends BattlePhase {
|
||||
public readonly phaseName = "PartyHealPhase";
|
||||
@ -15,18 +17,27 @@ export class PartyHealPhase extends BattlePhase {
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
const isHealPhaseActive = new BooleanHolder(true);
|
||||
const isReviveActive = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.NO_HEAL_PHASE, isHealPhaseActive);
|
||||
applyChallenges(ChallengeType.PREVENT_REVIVE, isReviveActive);
|
||||
if (!isHealPhaseActive.value) {
|
||||
return this.end();
|
||||
}
|
||||
const bgmPlaying = globalScene.isBgmPlaying();
|
||||
if (bgmPlaying) {
|
||||
globalScene.fadeOutBgm(1000, false);
|
||||
}
|
||||
globalScene.ui.fadeOut(1000).then(() => {
|
||||
for (const pokemon of globalScene.getPlayerParty()) {
|
||||
pokemon.hp = pokemon.getMaxHp();
|
||||
pokemon.resetStatus(true, false, false, true);
|
||||
for (const move of pokemon.moveset) {
|
||||
move.ppUsed = 0;
|
||||
if (isReviveActive.value || !pokemon.isFainted()) {
|
||||
pokemon.hp = pokemon.getMaxHp();
|
||||
pokemon.resetStatus(true, false, false, true);
|
||||
for (const move of pokemon.moveset) {
|
||||
move.ppUsed = 0;
|
||||
}
|
||||
pokemon.updateInfo(true);
|
||||
}
|
||||
pokemon.updateInfo(true);
|
||||
}
|
||||
const healSong = globalScene.playSoundWithoutBgm("heal");
|
||||
globalScene.time.delayedCall(fixedInt(healSong.totalDuration * 1000), () => {
|
||||
|
@ -8,6 +8,10 @@ import { handleMysteryEncounterVictory } from "#app/data/mystery-encounters/util
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { timedEventManager } from "#app/global-event-manager";
|
||||
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
import { BooleanHolder } from "#app/utils/common";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
|
||||
export class VictoryPhase extends PokemonPhase {
|
||||
public readonly phaseName = "VictoryPhase";
|
||||
/** If true, indicates that the phase is intended for EXP purposes only, and not to continue a battle to next phase */
|
||||
@ -37,6 +41,8 @@ export class VictoryPhase extends PokemonPhase {
|
||||
return this.end();
|
||||
}
|
||||
|
||||
const isHealPhaseActive = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.NO_HEAL_PHASE, isHealPhaseActive);
|
||||
if (
|
||||
!globalScene
|
||||
.getEnemyParty()
|
||||
@ -104,6 +110,15 @@ export class VictoryPhase extends PokemonPhase {
|
||||
);
|
||||
globalScene.phaseManager.pushNew("AddEnemyBuffModifierPhase");
|
||||
}
|
||||
if (!isHealPhaseActive.value) {
|
||||
//Push shop instead of healing phase for NoHealChallenge
|
||||
globalScene.phaseManager.pushNew(
|
||||
"SelectModifierPhase",
|
||||
undefined,
|
||||
undefined,
|
||||
this.getFixedBattleCustomModifiers(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
|
||||
|
@ -16,6 +16,9 @@ import i18next from "i18next";
|
||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||
import Phaser from "phaser";
|
||||
import type { PokeballType } from "#enums/pokeball";
|
||||
import { applyChallenges } from "#app/data/challenge";
|
||||
import { ChallengeType } from "#enums/challenge-type";
|
||||
import { BooleanHolder } from "#app/utils/common";
|
||||
|
||||
export const SHOP_OPTIONS_ROW_LIMIT = 7;
|
||||
const SINGLE_SHOP_ROW_YOFFSET = 12;
|
||||
@ -211,9 +214,16 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
const removeHealShop = globalScene.gameMode.hasNoShop;
|
||||
const baseShopCost = new NumberHolder(globalScene.getWaveMoneyAmount(1));
|
||||
globalScene.applyModifier(HealShopCostModifier, true, baseShopCost);
|
||||
const shopTypeOptions = !removeHealShop
|
||||
? getPlayerShopModifierTypeOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value)
|
||||
: [];
|
||||
const shopTypeOptions = removeHealShop
|
||||
? []
|
||||
: getPlayerShopModifierTypeOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value).filter(
|
||||
shopItem => {
|
||||
const isValidForChallenge = new BooleanHolder(true);
|
||||
applyChallenges(ChallengeType.SHOP_ITEM_BLACKLIST, shopItem, isValidForChallenge);
|
||||
return isValidForChallenge.value;
|
||||
},
|
||||
);
|
||||
|
||||
const optionsYOffset =
|
||||
shopTypeOptions.length > SHOP_OPTIONS_ROW_LIMIT ? -SINGLE_SHOP_ROW_YOFFSET : -DOUBLE_SHOP_ROW_YOFFSET;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user