Updated No Free heal challenge to implement two other modes and applied minor adjustments on challenge.ts file

Signed-off-by: Matilde Simões <matilde.simoes@tecnico.ulisboa.pt>
    Co-authored-by: Fuad Ali <fuad.ali@tecnico.ulisboa.pt>
This commit is contained in:
Matilde Simões 2025-07-02 20:20:41 +01:00
parent 68e1ee84f9
commit c4c4fdfd21
3 changed files with 73 additions and 26 deletions

View File

@ -1,4 +1,4 @@
import { BooleanHolder, type NumberHolder, randSeedItem } from "#app/utils/common"; import { BooleanHolder, type NumberHolder, randSeedItem, isNullOrUndefined } from "#app/utils/common";
import { deepCopy } from "#app/utils/data"; import { deepCopy } from "#app/utils/data";
import i18next from "i18next"; import i18next from "i18next";
import type { DexAttrProps, GameData } from "#app/system/game-data"; import type { DexAttrProps, GameData } from "#app/system/game-data";
@ -357,13 +357,22 @@ export abstract class Challenge {
return false; return false;
} }
/**
* An apply function for NO_SHOP_PHASE. Derived classes should alter this.
* @param _applyShopPhase {@link BooleanHolder} Whether it should apply the shop phase.
* @returns {@link boolean} if this function did anything.
*/
applyNoShopPhase(_applyShopPhase: BooleanHolder): boolean {
return false;
}
/** /**
* An apply function for PREVENT_REVIVE. Derived classes should alter this. * An apply function for PREVENT_REVIVE. Derived classes should alter this.
* @param _canBeRevived {@link BooleanHolder} Whether it should revive the fainted Pokemon. * @param _canBeRevived {@link BooleanHolder} Whether it should revive the fainted Pokemon.
* @returns {@link boolean} if this function did anything. * @returns {@link boolean} if this function did anything.
*/ */
applyRevivePrevention(_canBeRevived: BooleanHolder): boolean { applyRevivePrevention(_canBeRevived: BooleanHolder): boolean {
return true; return false;
} }
/** /**
@ -974,12 +983,23 @@ export class LowerStarterPointsChallenge extends Challenge {
*/ */
export class NoFreeHealsChallenge extends Challenge { export class NoFreeHealsChallenge extends Challenge {
constructor() { constructor() {
super(Challenges.NO_AUTO_HEAL, 1); super(Challenges.NO_AUTO_HEAL, 3);
} }
applyNoHealPhase(applyHealPhase: BooleanHolder): boolean { applyNoHealPhase(applyHealPhase: BooleanHolder): boolean {
applyHealPhase.value = false; if (this.value !== 1) {
return true; applyHealPhase.value = false;
return true;
}
return false;
}
applyNoShopPhase(applyShopPhase: BooleanHolder): boolean {
if (this.value !== 2) {
applyShopPhase.value = false;
return true;
}
return false;
} }
static loadChallenge(source: NoFreeHealsChallenge | any): NoFreeHealsChallenge { static loadChallenge(source: NoFreeHealsChallenge | any): NoFreeHealsChallenge {
@ -1001,6 +1021,8 @@ export class HardcoreChallenge extends Challenge {
"modifierType:ModifierType.REVIVER_SEED", "modifierType:ModifierType.REVIVER_SEED",
]; ];
private moveBlacklist = [MoveId.REVIVAL_BLESSING];
constructor() { constructor() {
super(Challenges.HARDCORE, 2); super(Challenges.HARDCORE, 2);
} }
@ -1018,9 +1040,11 @@ export class HardcoreChallenge extends Challenge {
} }
applyMoveBlacklist(move: PokemonMove, moveCanBeUsed: BooleanHolder): boolean { applyMoveBlacklist(move: PokemonMove, moveCanBeUsed: BooleanHolder): boolean {
const moveBlacklist = [MoveId.REVIVAL_BLESSING]; if (this.moveBlacklist.includes(move.moveId)) {
moveCanBeUsed.value = !moveBlacklist.includes(move.moveId); moveCanBeUsed.value = false;
return true; return true;
}
return false;
} }
applyRevivePrevention(canBeRevived: BooleanHolder): boolean { applyRevivePrevention(canBeRevived: BooleanHolder): boolean {
@ -1033,15 +1057,17 @@ export class HardcoreChallenge extends Challenge {
canStay.value = false; canStay.value = false;
} else { } else {
canStay.value = true; canStay.value = true;
return true;
} }
return true; return false;
} }
override applyShouldFuse(pokemon: Pokemon, pokemonToFuse: Pokemon, canFuse: BooleanHolder): boolean { override applyShouldFuse(pokemon: Pokemon, pokemonToFuse: Pokemon, canFuse: BooleanHolder): boolean {
if (pokemon!.isFainted() || pokemonToFuse.isFainted()) { if (pokemon!.isFainted() || pokemonToFuse.isFainted()) {
canFuse.value = false; canFuse.value = false;
return true;
} }
return true; return false;
} }
static override loadChallenge(source: HardcoreChallenge | any): HardcoreChallenge { static override loadChallenge(source: HardcoreChallenge | any): HardcoreChallenge {
@ -1068,14 +1094,17 @@ export class LimitedCatchChallenge extends Challenge {
} }
override applyAddPokemonToParty(waveIndex: number, canAddToParty: BooleanHolder): boolean { override applyAddPokemonToParty(waveIndex: number, canAddToParty: BooleanHolder): boolean {
const lastMystery = globalScene.lastMysteryEncounter?.encounterType; if (waveIndex % 10 !== 1) {
if (lastMystery === undefined && !(waveIndex % 10 === 1)) { const lastMystery = globalScene.lastMysteryEncounter?.encounterType;
canAddToParty.value = false; if (
isNullOrUndefined(lastMystery) ||
!(waveIndex % 10 === 2 && !this.mysteryEncounterBlacklist.includes(lastMystery!))
) {
canAddToParty.value = false;
return true;
}
return false;
} }
if (!(waveIndex % 10 === 1) && !(!this.mysteryEncounterBlacklist.includes(lastMystery!) && waveIndex % 10 === 2)) {
canAddToParty.value = false;
}
return true;
} }
static override loadChallenge(source: LimitedCatchChallenge | any): LimitedCatchChallenge { static override loadChallenge(source: LimitedCatchChallenge | any): LimitedCatchChallenge {
@ -1244,6 +1273,14 @@ export function applyChallenges(challengeType: ChallengeType.FLIP_STAT, pokemon:
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(challengeType: ChallengeType.NO_HEAL_PHASE, applyHealPhase: BooleanHolder): boolean; export function applyChallenges(challengeType: ChallengeType.NO_HEAL_PHASE, applyHealPhase: BooleanHolder): boolean;
/**
* Apply all challenges that modify whether the shop will appear.
* @param challengeType {@link ChallengeType} ChallengeType.NO_SHOP_PHASE
* @param applyShopPhase {@link BooleanHolder} Whether it should apply the shop phase.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(challengeType: ChallengeType.NO_SHOP_PHASE, applyShopPhase: BooleanHolder): boolean;
/** /**
* Apply all challenges that modify whether a shop item should be blacklisted. * Apply all challenges that modify whether a shop item should be blacklisted.
* @param challengeType {@link ChallengeType} ChallengeType.SHOP_ITEM_BLACKLIST * @param challengeType {@link ChallengeType} ChallengeType.SHOP_ITEM_BLACKLIST
@ -1372,6 +1409,9 @@ export function applyChallenges(challengeType: ChallengeType, ...args: any[]): b
case ChallengeType.NO_HEAL_PHASE: case ChallengeType.NO_HEAL_PHASE:
ret ||= c.applyNoHealPhase(args[0]); ret ||= c.applyNoHealPhase(args[0]);
break; break;
case ChallengeType.NO_SHOP_PHASE:
ret ||= c.applyNoShopPhase(args[0]);
break;
case ChallengeType.SHOP_ITEM_BLACKLIST: case ChallengeType.SHOP_ITEM_BLACKLIST:
ret ||= c.applyShopItemBlacklist(args[0], args[1]); ret ||= c.applyShopItemBlacklist(args[0], args[1]);
break; break;

View File

@ -70,6 +70,10 @@ export enum ChallengeType {
* Challenge that modifies if the player should auto heal every 10th wave * Challenge that modifies if the player should auto heal every 10th wave
*/ */
NO_HEAL_PHASE, NO_HEAL_PHASE,
/**
* Challenge that modifies if the shop should appear
*/
NO_SHOP_PHASE,
/** /**
* Modifies if the shop item is blacklisted * Modifies if the shop item is blacklisted
* @see {@linkcode Challenge.applyShopItemBlacklist} * @see {@linkcode Challenge.applyShopItemBlacklist}

View File

@ -214,15 +214,18 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
const removeHealShop = globalScene.gameMode.hasNoShop; const removeHealShop = globalScene.gameMode.hasNoShop;
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 isShopActive = new BooleanHolder(true);
? [] applyChallenges(ChallengeType.NO_SHOP_PHASE, isShopActive);
: getPlayerShopModifierTypeOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value).filter( const shopTypeOptions =
shopItem => { removeHealShop || !isShopActive.value
const isValidForChallenge = new BooleanHolder(true); ? []
applyChallenges(ChallengeType.SHOP_ITEM_BLACKLIST, shopItem, isValidForChallenge); : getPlayerShopModifierTypeOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value).filter(
return isValidForChallenge.value; shopItem => {
}, const isValidForChallenge = new BooleanHolder(true);
); applyChallenges(ChallengeType.SHOP_ITEM_BLACKLIST, shopItem, isValidForChallenge);
return isValidForChallenge.value;
},
);
const optionsYOffset = const optionsYOffset =
shopTypeOptions.length > SHOP_OPTIONS_ROW_LIMIT ? -SINGLE_SHOP_ROW_YOFFSET : -DOUBLE_SHOP_ROW_YOFFSET; shopTypeOptions.length > SHOP_OPTIONS_ROW_LIMIT ? -SINGLE_SHOP_ROW_YOFFSET : -DOUBLE_SHOP_ROW_YOFFSET;