Add Challenges (#1459)
* Initial challenge framework * Add type localisation * Change how challenges are tracked Also fixes the difficulty total text * MVP Renames challenge types, temporarily hides difficulty, and implements challenge saving. * Attempt to fix one legal pokemon in a double battle * Make monotype ignore type changing effects * Make isOfType correctly detect normal types * Try to fix double battles again * Make challenge function more like classic * Add helper function for fainted or not allowed * Add framework for fresh start challenge and improve comments * Try to fix evolution issues * Make form changing items only usable from rewards screen * Update localisation * Additional localisation change * Add achievements for completing challenges * Fix initialisation bug with challenge achievements * Add support for gamemode specific fixed battles Also make monogen challenges face the e4 of their generation * Add better support for mobile in challenges * Localise illegal evolution/form change message * Update achievement names * Make alternate forms count for monogen * Update monotype achievement icons * Add more comments * Improve comments * Fix mid battle form changes * Reorder mode list * Remove currently unused localisation entry * Add type overrides for monotype challenges Meloetta always counts for psychic and castform always counts for normal * Change how form changes are handled Now attempts a switch at the start of each turn instead of immediately * Add start button to challenge select screen * Make starter select back out to challenge screen if using challenges * Fix daily runs * Update tests to new game mode logic
This commit is contained in:
parent
9c97e37c27
commit
696ff6eae3
|
@ -20,8 +20,8 @@ import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesF
|
|||
import AbilityBar from "./ui/ability-bar";
|
||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
|
||||
import { allAbilities } from "./data/ability";
|
||||
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from "./battle";
|
||||
import { GameMode, GameModes, gameModes } from "./game-mode";
|
||||
import Battle, { BattleType, FixedBattleConfig } from "./battle";
|
||||
import { GameMode, GameModes, getGameMode } from "./game-mode";
|
||||
import FieldSpritePipeline from "./pipelines/field-sprite";
|
||||
import SpritePipeline from "./pipelines/sprite";
|
||||
import PartyExpBar from "./ui/party-exp-bar";
|
||||
|
@ -853,7 +853,7 @@ export default class BattleScene extends SceneBase {
|
|||
this.gameData = new GameData(this);
|
||||
}
|
||||
|
||||
this.gameMode = gameModes[GameModes.CLASSIC];
|
||||
this.gameMode = getGameMode(GameModes.CLASSIC);
|
||||
|
||||
this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24));
|
||||
console.log("Seed:", this.seed);
|
||||
|
@ -961,8 +961,8 @@ export default class BattleScene extends SceneBase {
|
|||
|
||||
const playerField = this.getPlayerField();
|
||||
|
||||
if (this.gameMode.hasFixedBattles && fixedBattles.hasOwnProperty(newWaveIndex) && trainerData === undefined) {
|
||||
battleConfig = fixedBattles[newWaveIndex];
|
||||
if (this.gameMode.isFixedBattle(newWaveIndex) && trainerData === undefined) {
|
||||
battleConfig = this.gameMode.getFixedBattle(newWaveIndex);
|
||||
newDouble = battleConfig.double;
|
||||
newBattleType = battleConfig.battleType;
|
||||
this.executeWithSeedOffset(() => newTrainer = battleConfig.getTrainer(this), (battleConfig.seedOffsetWaveIndex || newWaveIndex) << 8);
|
||||
|
|
|
@ -416,11 +416,11 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): Get
|
|||
};
|
||||
}
|
||||
|
||||
interface FixedBattleConfigs {
|
||||
export interface FixedBattleConfigs {
|
||||
[key: integer]: FixedBattleConfig
|
||||
}
|
||||
|
||||
export const fixedBattles: FixedBattleConfigs = {
|
||||
export const classicFixedBattles: FixedBattleConfigs = {
|
||||
[5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||
[8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||
|
|
|
@ -0,0 +1,568 @@
|
|||
import * as Utils from "../utils";
|
||||
import { Challenges } from "./enums/challenges";
|
||||
import i18next from "#app/plugins/i18n.js";
|
||||
import { GameData } from "#app/system/game-data.js";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./pokemon-species";
|
||||
import Pokemon from "#app/field/pokemon.js";
|
||||
import { BattleType, FixedBattleConfig } from "#app/battle.js";
|
||||
import { TrainerType } from "./enums/trainer-type";
|
||||
import Trainer, { TrainerVariant } from "#app/field/trainer.js";
|
||||
import { GameMode } from "#app/game-mode.js";
|
||||
import { Species } from "./enums/species";
|
||||
import { Type } from "./type";
|
||||
|
||||
/**
|
||||
* An enum for all the challenge types. The parameter entries on these describe the
|
||||
* parameters to use when calling the applyChallenges function.
|
||||
*/
|
||||
export enum ChallengeType {
|
||||
/**
|
||||
* Challenges which modify what starters you can choose
|
||||
* @param args [0] {@link PokemonSpecies} The species to check
|
||||
* [1] {@link Utils.BooleanHolder} Sets to false if illegal, pass in true.
|
||||
*/
|
||||
STARTER_CHOICE,
|
||||
/**
|
||||
* Challenges which modify how many starter points you have
|
||||
* @param args [0] {@link Utils.NumberHolder} The amount of starter points you have
|
||||
*/
|
||||
STARTER_POINTS,
|
||||
/**
|
||||
* Challenges which modify your starters in some way
|
||||
* Not Fully Implemented
|
||||
*/
|
||||
STARTER_MODIFY,
|
||||
/**
|
||||
* Challenges which limit which pokemon you can have in battle.
|
||||
* @param args [0] {@link Pokemon} The pokemon to check
|
||||
* [1] {@link Utils.BooleanHolder} Sets to false if illegal, pass in true.
|
||||
*/
|
||||
POKEMON_IN_BATTLE,
|
||||
/**
|
||||
* Adds or modifies the fixed battles in a run
|
||||
* @param args [0] integer The wave to get a battle for
|
||||
* [1] {@link FixedBattleConfig} A new fixed battle. It'll be modified if a battle exists.
|
||||
*/
|
||||
FIXED_BATTLES,
|
||||
}
|
||||
|
||||
/**
|
||||
* A challenge object. Exists only to serve as a base class.
|
||||
*/
|
||||
export abstract class Challenge {
|
||||
public id: Challenges; // The id of the challenge
|
||||
|
||||
public value: integer; // The "strength" of the challenge, all challenges have a numerical value.
|
||||
public maxValue: integer; // The maximum strength of the challenge.
|
||||
public severity: integer; // The current severity of the challenge. Some challenges have multiple severities in addition to strength.
|
||||
public maxSeverity: integer; // The maximum severity of the challenge.
|
||||
|
||||
public conditions: ChallengeCondition[];
|
||||
public challengeTypes: ChallengeType[];
|
||||
|
||||
/**
|
||||
* @param {Challenges} id The enum value for the challenge
|
||||
*/
|
||||
constructor(id: Challenges, maxValue: integer = Number.MAX_SAFE_INTEGER) {
|
||||
this.id = id;
|
||||
|
||||
this.value = 0;
|
||||
this.maxValue = maxValue;
|
||||
this.severity = 0;
|
||||
this.maxSeverity = 0;
|
||||
this.conditions = [];
|
||||
this.challengeTypes = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the challenge to a base state.
|
||||
*/
|
||||
reset(): void {
|
||||
this.value = 0;
|
||||
this.severity = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the localisation key for the challenge
|
||||
* @returns The i18n key for this challenge
|
||||
*/
|
||||
geti18nKey(): string {
|
||||
return Challenges[this.id].split("_").map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for unlockable challenges to check if they're unlocked.
|
||||
* @param {GameData} data The save data.
|
||||
* @returns {boolean} Whether this challenge is unlocked.
|
||||
*/
|
||||
isUnlocked(data: GameData): boolean {
|
||||
return this.conditions.every(f => f(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an unlock condition to this challenge.
|
||||
* @param {ChallengeCondition} condition The condition to add.
|
||||
* @returns {Challenge} This challenge
|
||||
*/
|
||||
condition(condition: ChallengeCondition): Challenge {
|
||||
this.conditions.push(condition);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this challenge is of a particular type
|
||||
* @param {ChallengeType} challengeType The challenge type to check.
|
||||
* @returns {Challenge} This challenge
|
||||
*/
|
||||
isOfType(challengeType: ChallengeType): boolean {
|
||||
return this.challengeTypes.some(c => c === challengeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a challenge type to this challenge.
|
||||
* @param {ChallengeType} challengeType The challenge type to add.
|
||||
* @returns {Challenge} This challenge
|
||||
*/
|
||||
addChallengeType(challengeType: ChallengeType): Challenge {
|
||||
this.challengeTypes.push(challengeType);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} The localised name of this challenge.
|
||||
*/
|
||||
getName(): string {
|
||||
return i18next.t(`challenges:${this.geti18nKey()}.name`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the textual representation of a challenge's current value.
|
||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
||||
* @returns {string} The localised name for the current value.
|
||||
*/
|
||||
getValue(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return i18next.t(`challenges:${this.geti18nKey()}.value.${this.value}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of a challenge's current value.
|
||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
||||
* @returns {string} The localised description for the current value.
|
||||
*/
|
||||
getDescription(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return i18next.t(`challenges:${this.geti18nKey()}.desc.${this.value}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the value of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
increaseValue(): boolean {
|
||||
if (this.value < this.maxValue) {
|
||||
this.value = Math.min(this.value + 1, this.maxValue);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the value of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
decreaseValue(): boolean {
|
||||
if (this.value > 0) {
|
||||
this.value = Math.max(this.value - 1, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to allow choosing this challenge's severity.
|
||||
*/
|
||||
hasSeverity(): boolean {
|
||||
return this.value !== 0 && this.maxSeverity > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the severity of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
decreaseSeverity(): boolean {
|
||||
if (this.severity > 0) {
|
||||
this.severity = Math.max(this.severity - 1, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the severity of the challenge
|
||||
* @returns {boolean} Returns true if the value changed
|
||||
*/
|
||||
increaseSeverity(): boolean {
|
||||
if (this.severity < this.maxSeverity) {
|
||||
this.severity = Math.min(this.severity + 1, this.maxSeverity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "difficulty" value of this challenge.
|
||||
* @returns {integer} The difficulty value.
|
||||
*/
|
||||
getDifficulty(): integer {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum difficulty added by this challenge.
|
||||
* @returns {integer} The difficulty value.
|
||||
*/
|
||||
getMinDifficulty(): integer {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the data or game state in some way to apply the challenge.
|
||||
* @param {ChallengeType} challengeType Which challenge type this is being applied for.
|
||||
* @param args Irrelevant. See the specific challenge's apply function for additional information.
|
||||
*/
|
||||
abstract apply(challengeType: ChallengeType, args: any[]): boolean;
|
||||
|
||||
/**
|
||||
* Clones a challenge, either from another challenge or json. Chainable.
|
||||
* @param {Challenge | any} source The source challenge of json.
|
||||
* @returns {Challenge} This challenge.
|
||||
*/
|
||||
static loadChallenge(source: Challenge | any): Challenge {
|
||||
throw new Error("Method not implemented! Use derived class");
|
||||
}
|
||||
}
|
||||
|
||||
type ChallengeCondition = (data: GameData) => boolean;
|
||||
|
||||
/**
|
||||
* Implements a mono generation challenge.
|
||||
*/
|
||||
export class SingleGenerationChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.SINGLE_GENERATION, 9);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
this.addChallengeType(ChallengeType.POKEMON_IN_BATTLE);
|
||||
this.addChallengeType(ChallengeType.FIXED_BATTLES);
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValidStarter = args[1] as Utils.BooleanHolder;
|
||||
if (species.generation !== this.value) {
|
||||
isValidStarter.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ChallengeType.POKEMON_IN_BATTLE:
|
||||
const pokemon = args[0] as Pokemon;
|
||||
const isValidPokemon = args[1] as Utils.BooleanHolder;
|
||||
if (pokemon.isPlayer() && ((pokemon.species.formIndex === 0 ? pokemon.species : getPokemonSpecies(pokemon.species.speciesId)).generation !== this.value || (pokemon.isFusion() && (pokemon.fusionSpecies.formIndex === 0 ? pokemon.fusionSpecies : getPokemonSpecies(pokemon.fusionSpecies.speciesId)).generation !== this.value))) {
|
||||
isValidPokemon.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ChallengeType.FIXED_BATTLES:
|
||||
const waveIndex = args[0] as integer;
|
||||
const battleConfig = args[1] as FixedBattleConfig;
|
||||
let trainerTypes: TrainerType[] = [];
|
||||
switch (waveIndex) {
|
||||
case 182:
|
||||
trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]),TrainerType.MARNIE_ELITE, TrainerType.RIKA ];
|
||||
break;
|
||||
case 184:
|
||||
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
|
||||
break;
|
||||
case 186:
|
||||
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([TrainerType.BEA_ELITE,TrainerType.ALLISTER_ELITE]), TrainerType.LARRY_ELITE ];
|
||||
break;
|
||||
case 188:
|
||||
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
|
||||
break;
|
||||
case 190:
|
||||
trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ];
|
||||
break;
|
||||
}
|
||||
if (trainerTypes.length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
battleConfig.setBattleType(BattleType.TRAINER).setGetTrainerFunc(scene => new Trainer(scene, trainerTypes[this.value - 1], TrainerVariant.DEFAULT));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
*/
|
||||
getDifficulty(): number {
|
||||
return this.value > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static loadChallenge(source: SingleGenerationChallenge | any): SingleGenerationChallenge {
|
||||
const newChallenge = new SingleGenerationChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
interface monotypeOverride {
|
||||
/** The species to override */
|
||||
species: Species;
|
||||
/** The type to count as */
|
||||
type: Type;
|
||||
/** If part of a fusion, should we check the fused species instead of the base species? */
|
||||
fusion: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a mono type challenge.
|
||||
*/
|
||||
export class SingleTypeChallenge extends Challenge {
|
||||
private static TYPE_OVERRIDES: monotypeOverride[] = [
|
||||
{species: Species.MELOETTA, type: Type.PSYCHIC, fusion: true},
|
||||
{species: Species.CASTFORM, type: Type.NORMAL, fusion: false},
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super(Challenges.SINGLE_TYPE, 18);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
this.addChallengeType(ChallengeType.POKEMON_IN_BATTLE);
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValidStarter = args[1] as Utils.BooleanHolder;
|
||||
if (!species.isOfType(this.value - 1)) {
|
||||
isValidStarter.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ChallengeType.POKEMON_IN_BATTLE:
|
||||
const pokemon = args[0] as Pokemon;
|
||||
const isValidPokemon = args[1] as Utils.BooleanHolder;
|
||||
if (pokemon.isPlayer() && !pokemon.isOfType(this.value - 1, false, false, true)
|
||||
&& !SingleTypeChallenge.TYPE_OVERRIDES.some(o => o.type === (this.value - 1) && (pokemon.isFusion() && o.fusion ? pokemon.fusionSpecies : pokemon.species).speciesId === o.species)) {
|
||||
isValidPokemon.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
*/
|
||||
getDifficulty(): number {
|
||||
return this.value > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static loadChallenge(source: SingleTypeChallenge | any): SingleTypeChallenge {
|
||||
const newChallenge = new SingleTypeChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a fresh start challenge.
|
||||
*/
|
||||
export class FreshStartChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.FRESH_START, 1);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
this.addChallengeType(ChallengeType.STARTER_MODIFY);
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValidStarter = args[1] as Utils.BooleanHolder;
|
||||
if (species) {
|
||||
isValidStarter.value = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
*/
|
||||
getDifficulty(): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static loadChallenge(source: FreshStartChallenge | any): FreshStartChallenge {
|
||||
const newChallenge = new FreshStartChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lowers the amount of starter points available.
|
||||
*/
|
||||
export class LowerStarterMaxCostChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.LOWER_MAX_STARTER_COST, 9);
|
||||
this.addChallengeType(ChallengeType.STARTER_CHOICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getValue(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return (10 - overrideValue).toString();
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_CHOICE:
|
||||
const species = args[0] as PokemonSpecies;
|
||||
const isValid = args[1] as Utils.BooleanHolder;
|
||||
if (speciesStarters[species.speciesId] > 10 - this.value) {
|
||||
isValid.value = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static loadChallenge(source: LowerStarterMaxCostChallenge | any): LowerStarterMaxCostChallenge {
|
||||
const newChallenge = new LowerStarterMaxCostChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lowers the maximum cost of starters available.
|
||||
*/
|
||||
export class LowerStarterPointsChallenge extends Challenge {
|
||||
constructor() {
|
||||
super(Challenges.LOWER_STARTER_POINTS, 9);
|
||||
this.addChallengeType(ChallengeType.STARTER_POINTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getValue(overrideValue?: integer): string {
|
||||
if (overrideValue === undefined) {
|
||||
overrideValue = this.value;
|
||||
}
|
||||
return (10 - overrideValue).toString();
|
||||
}
|
||||
|
||||
apply(challengeType: ChallengeType, args: any[]): boolean {
|
||||
if (this.value === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (challengeType) {
|
||||
case ChallengeType.STARTER_POINTS:
|
||||
const points = args[0] as Utils.NumberHolder;
|
||||
points.value -= this.value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static loadChallenge(source: LowerStarterPointsChallenge | any): LowerStarterPointsChallenge {
|
||||
const newChallenge = new LowerStarterPointsChallenge();
|
||||
newChallenge.value = source.value;
|
||||
newChallenge.severity = source.severity;
|
||||
return newChallenge;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all challenges of a given challenge type.
|
||||
* @param {BattleScene} scene The current scene
|
||||
* @param {ChallengeType} challengeType What challenge type to apply
|
||||
* @param {any[]} args Any args for that challenge type
|
||||
* @returns {boolean} True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean {
|
||||
let ret = false;
|
||||
gameMode.challenges.forEach(v => {
|
||||
if (v.isOfType(challengeType)) {
|
||||
ret ||= v.apply(challengeType, args);
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function copyChallenge(source: Challenge | any): Challenge {
|
||||
switch (source.id) {
|
||||
case Challenges.SINGLE_GENERATION:
|
||||
return SingleGenerationChallenge.loadChallenge(source);
|
||||
case Challenges.SINGLE_TYPE:
|
||||
return SingleTypeChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_MAX_STARTER_COST:
|
||||
return LowerStarterMaxCostChallenge.loadChallenge(source);
|
||||
case Challenges.LOWER_STARTER_POINTS:
|
||||
return LowerStarterPointsChallenge.loadChallenge(source);
|
||||
}
|
||||
throw new Error("Unknown challenge copied");
|
||||
}
|
||||
|
||||
export const allChallenges: Challenge[] = [];
|
||||
|
||||
export function initChallenges() {
|
||||
allChallenges.push(
|
||||
new SingleGenerationChallenge(),
|
||||
new SingleTypeChallenge(),
|
||||
// new LowerStarterMaxCostChallenge(),
|
||||
// new LowerStarterPointsChallenge(),
|
||||
// new FreshStartChallenge()
|
||||
);
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import BattleScene from "../battle-scene";
|
||||
import { PlayerPokemon } from "../field/pokemon";
|
||||
import { GameModes, gameModes } from "../game-mode";
|
||||
import { Starter } from "../ui/starter-select-ui-handler";
|
||||
import * as Utils from "../utils";
|
||||
import { Species } from "./enums/species";
|
||||
|
@ -29,7 +28,7 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
|
|||
const starters: Starter[] = [];
|
||||
|
||||
scene.executeWithSeedOffset(() => {
|
||||
const startingLevel = gameModes[GameModes.DAILY].getStartingLevel();
|
||||
const startingLevel = scene.gameMode.getStartingLevel();
|
||||
|
||||
if (/\d{18}$/.test(seed)) {
|
||||
for (let s = 0; s < 3; s++) {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export enum Challenges {
|
||||
SINGLE_GENERATION,
|
||||
SINGLE_TYPE,
|
||||
LOWER_MAX_STARTER_COST,
|
||||
LOWER_STARTER_POINTS,
|
||||
FRESH_START
|
||||
}
|
|
@ -531,6 +531,11 @@ export class EvolutionPhase extends Phase {
|
|||
}
|
||||
|
||||
export class EndEvolutionPhase extends Phase {
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
}
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ import { BerryType } from "../data/enums/berry-type";
|
|||
import i18next from "../plugins/i18n";
|
||||
import { speciesEggMoves } from "../data/egg-moves";
|
||||
import { ModifierTier } from "../modifier/modifier-tier";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge.js";
|
||||
|
||||
export enum FieldPosition {
|
||||
CENTER,
|
||||
|
@ -266,11 +267,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return !this.hp && (!checkStatus || this.status?.effect === StatusEffect.FAINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this pokemon is both not fainted and allowed to be in battle.
|
||||
* This is frequently a better alternative to {@link isFainted}
|
||||
* @returns {boolean} True if pokemon is allowed in battle
|
||||
*/
|
||||
isAllowedInBattle(): boolean {
|
||||
const challengeAllowed = new Utils.BooleanHolder(true);
|
||||
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed);
|
||||
return !this.isFainted() && challengeAllowed.value;
|
||||
}
|
||||
|
||||
isActive(onField?: boolean): boolean {
|
||||
if (!this.scene) {
|
||||
return false;
|
||||
}
|
||||
return !this.isFainted() && !!this.scene && (!onField || this.isOnField());
|
||||
return this.isAllowedInBattle() && !!this.scene && (!onField || this.isOnField());
|
||||
}
|
||||
|
||||
getDexAttr(): bigint {
|
||||
|
@ -885,8 +897,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return types;
|
||||
}
|
||||
|
||||
isOfType(type: Type, forDefend: boolean = false): boolean {
|
||||
return !!this.getTypes(true, forDefend).find(t => t === type);
|
||||
isOfType(type: Type, includeTeraType: boolean = true, forDefend: boolean = false, ignoreOverride?: boolean): boolean {
|
||||
return !!this.getTypes(includeTeraType, forDefend, ignoreOverride).some(t => t === type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1054,7 +1066,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
isGrounded(): boolean {
|
||||
return !this.isOfType(Type.FLYING, true) && !this.hasAbility(Abilities.LEVITATE);
|
||||
return !this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE);
|
||||
}
|
||||
|
||||
getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove): TypeDamageMultiplier {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fixedBattles } from "./battle";
|
||||
import { classicFixedBattles, FixedBattleConfig, FixedBattleConfigs } from "./battle";
|
||||
import BattleScene from "./battle-scene";
|
||||
import { Biome } from "./data/enums/biome";
|
||||
import { Species } from "./data/enums/species";
|
||||
|
@ -6,12 +6,14 @@ import PokemonSpecies, { allSpecies } from "./data/pokemon-species";
|
|||
import { Arena } from "./field/arena";
|
||||
import * as Utils from "./utils";
|
||||
import * as Overrides from "./overrides";
|
||||
import { allChallenges, applyChallenges, Challenge, ChallengeType, copyChallenge } from "./data/challenge";
|
||||
|
||||
export enum GameModes {
|
||||
CLASSIC,
|
||||
ENDLESS,
|
||||
SPLICED_ENDLESS,
|
||||
DAILY
|
||||
DAILY,
|
||||
CHALLENGE
|
||||
}
|
||||
|
||||
interface GameModeConfig {
|
||||
|
@ -19,12 +21,12 @@ interface GameModeConfig {
|
|||
isEndless?: boolean;
|
||||
isDaily?: boolean;
|
||||
hasTrainers?: boolean;
|
||||
hasFixedBattles?: boolean;
|
||||
hasNoShop?: boolean;
|
||||
hasShortBiomes?: boolean;
|
||||
hasRandomBiomes?: boolean;
|
||||
hasRandomBosses?: boolean;
|
||||
isSplicedOnly?: boolean;
|
||||
isChallenge?: boolean;
|
||||
}
|
||||
|
||||
export class GameMode implements GameModeConfig {
|
||||
|
@ -33,16 +35,23 @@ export class GameMode implements GameModeConfig {
|
|||
public isEndless: boolean;
|
||||
public isDaily: boolean;
|
||||
public hasTrainers: boolean;
|
||||
public hasFixedBattles: boolean;
|
||||
public hasNoShop: boolean;
|
||||
public hasShortBiomes: boolean;
|
||||
public hasRandomBiomes: boolean;
|
||||
public hasRandomBosses: boolean;
|
||||
public isSplicedOnly: boolean;
|
||||
public isChallenge: boolean;
|
||||
public challenges: Challenge[];
|
||||
public battleConfig: FixedBattleConfigs;
|
||||
|
||||
constructor(modeId: GameModes, config: GameModeConfig) {
|
||||
constructor(modeId: GameModes, config: GameModeConfig, battleConfig?: FixedBattleConfigs) {
|
||||
this.modeId = modeId;
|
||||
this.challenges = [];
|
||||
Object.assign(this, config);
|
||||
if (this.isChallenge) {
|
||||
this.challenges = allChallenges.map(c => copyChallenge(c));
|
||||
}
|
||||
this.battleConfig = battleConfig || {};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,7 +121,7 @@ export class GameMode implements GameModeConfig {
|
|||
if (w === waveIndex) {
|
||||
continue;
|
||||
}
|
||||
if ((w % 30) === (arena.scene.offsetGym ? 0 : 20) || fixedBattles.hasOwnProperty(w)) {
|
||||
if ((w % 30) === (arena.scene.offsetGym ? 0 : 20) || this.isFixedBattle(waveIndex)) {
|
||||
allowTrainerBattle = false;
|
||||
break;
|
||||
} else if (w < waveIndex) {
|
||||
|
@ -161,6 +170,7 @@ export class GameMode implements GameModeConfig {
|
|||
isWaveFinal(waveIndex: integer, modeId: GameModes = this.modeId): boolean {
|
||||
switch (modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
return waveIndex === 200;
|
||||
case GameModes.ENDLESS:
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
|
@ -208,10 +218,36 @@ export class GameMode implements GameModeConfig {
|
|||
(this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there is a fixed battle on this gamemode on a given wave.
|
||||
* @param {integer} waveIndex The wave to check.
|
||||
* @returns {boolean} If this game mode has a fixed battle on this wave
|
||||
*/
|
||||
isFixedBattle(waveIndex: integer): boolean {
|
||||
const dummyConfig = new FixedBattleConfig();
|
||||
return this.battleConfig.hasOwnProperty(waveIndex) || applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, dummyConfig);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the config for the fixed battle for a particular wave.
|
||||
* @param {integer} waveIndex The wave to check.
|
||||
* @returns {boolean} The fixed battle for this wave.
|
||||
*/
|
||||
getFixedBattle(waveIndex: integer): FixedBattleConfig {
|
||||
const challengeConfig = new FixedBattleConfig();
|
||||
if (applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, challengeConfig)) {
|
||||
return challengeConfig;
|
||||
} else {
|
||||
return this.battleConfig[waveIndex];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getClearScoreBonus(): integer {
|
||||
switch (this.modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
return 5000;
|
||||
case GameModes.DAILY:
|
||||
return 2500;
|
||||
|
@ -221,6 +257,7 @@ export class GameMode implements GameModeConfig {
|
|||
getEnemyModifierChance(isBoss: boolean): integer {
|
||||
switch (this.modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
case GameModes.CHALLENGE:
|
||||
case GameModes.DAILY:
|
||||
return !isBoss ? 18 : 6;
|
||||
case GameModes.ENDLESS:
|
||||
|
@ -239,13 +276,38 @@ export class GameMode implements GameModeConfig {
|
|||
return "Endless (Spliced)";
|
||||
case GameModes.DAILY:
|
||||
return "Daily Run";
|
||||
case GameModes.CHALLENGE:
|
||||
return "Challenge";
|
||||
}
|
||||
}
|
||||
|
||||
static getModeName(modeId: GameModes): string {
|
||||
switch (modeId) {
|
||||
case GameModes.CLASSIC:
|
||||
return "Classic";
|
||||
case GameModes.ENDLESS:
|
||||
return "Endless";
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return "Endless (Spliced)";
|
||||
case GameModes.DAILY:
|
||||
return "Daily Run";
|
||||
case GameModes.CHALLENGE:
|
||||
return "Challenge";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const gameModes = Object.freeze({
|
||||
[GameModes.CLASSIC]: new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasFixedBattles: true }),
|
||||
[GameModes.ENDLESS]: new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }),
|
||||
[GameModes.SPLICED_ENDLESS]: new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true }),
|
||||
[GameModes.DAILY]: new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true })
|
||||
});
|
||||
export function getGameMode(gameMode: GameModes): GameMode {
|
||||
switch (gameMode) {
|
||||
case GameModes.CLASSIC:
|
||||
return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true }, classicFixedBattles);
|
||||
case GameModes.ENDLESS:
|
||||
return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true });
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true });
|
||||
case GameModes.DAILY:
|
||||
return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true });
|
||||
case GameModes.CHALLENGE:
|
||||
return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true }, classicFixedBattles);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import {initMoves} from "#app/data/move";
|
|||
import {initAbilities} from "#app/data/ability";
|
||||
import {initAchievements} from "#app/system/achv";
|
||||
import {initTrainerTypeDialogue} from "#app/data/dialogue";
|
||||
import { initChallenges } from "./data/challenge";
|
||||
import i18next from "i18next";
|
||||
import { initStatsKeys } from "./ui/game-stats-ui-handler";
|
||||
import { initVouchers } from "./system/voucher";
|
||||
|
@ -341,6 +342,7 @@ export class LoadingScene extends SceneBase {
|
|||
initSpecies();
|
||||
initMoves();
|
||||
initAbilities();
|
||||
initChallenges();
|
||||
}
|
||||
|
||||
loadLoadingScreen() {
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const deConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -168,4 +168,99 @@ export const achv: AchievementTranslationEntries = {
|
|||
name: "Undefeated",
|
||||
description: "Beat the game in classic mode",
|
||||
},
|
||||
|
||||
"MONO_GEN_ONE": {
|
||||
name: "The Original Rival",
|
||||
description: "Complete the generation one only challenge.",
|
||||
},
|
||||
"MONO_GEN_TWO": {
|
||||
name: "Generation 1.5",
|
||||
description: "Complete the generation two only challenge.",
|
||||
},
|
||||
"MONO_GEN_THREE": {
|
||||
name: "Too much water?",
|
||||
description: "Complete the generation three only challenge.",
|
||||
},
|
||||
"MONO_GEN_FOUR": {
|
||||
name: "Is she really the hardest?",
|
||||
description: "Complete the generation four only challenge.",
|
||||
},
|
||||
"MONO_GEN_FIVE": {
|
||||
name: "All Original",
|
||||
description: "Complete the generation five only challenge.",
|
||||
},
|
||||
"MONO_GEN_SIX": {
|
||||
name: "Almost Royalty",
|
||||
description: "Complete the generation six only challenge.",
|
||||
},
|
||||
"MONO_GEN_SEVEN": {
|
||||
name: "Only Technically",
|
||||
description: "Complete the generation seven only challenge.",
|
||||
},
|
||||
"MONO_GEN_EIGHT": {
|
||||
name: "A Champion Time!",
|
||||
description: "Complete the generation eight only challenge.",
|
||||
},
|
||||
"MONO_GEN_NINE": {
|
||||
name: "She was going easy on you",
|
||||
description: "Complete the generation nine only challenge.",
|
||||
},
|
||||
|
||||
"MonoType": {
|
||||
description: "Complete the {{type}} monotype challenge.",
|
||||
},
|
||||
"MONO_NORMAL": {
|
||||
name: "Mono NORMAL",
|
||||
},
|
||||
"MONO_FIGHTING": {
|
||||
name: "I Know Kung Fu",
|
||||
},
|
||||
"MONO_FLYING": {
|
||||
name: "Mono FLYING",
|
||||
},
|
||||
"MONO_POISON": {
|
||||
name: "Kanto's Favourite",
|
||||
},
|
||||
"MONO_GROUND": {
|
||||
name: "Mono GROUND",
|
||||
},
|
||||
"MONO_ROCK": {
|
||||
name: "Brock Hard",
|
||||
},
|
||||
"MONO_BUG": {
|
||||
name: "Sting Like A Beedrill",
|
||||
},
|
||||
"MONO_GHOST": {
|
||||
name: "Who you gonna call?",
|
||||
},
|
||||
"MONO_STEEL": {
|
||||
name: "Mono STEEL",
|
||||
},
|
||||
"MONO_FIRE": {
|
||||
name: "Mono FIRE",
|
||||
},
|
||||
"MONO_WATER": {
|
||||
name: "When It Rains, It Pours",
|
||||
},
|
||||
"MONO_GRASS": {
|
||||
name: "Mono GRASS",
|
||||
},
|
||||
"MONO_ELECTRIC": {
|
||||
name: "Mono ELECTRIC",
|
||||
},
|
||||
"MONO_PSYCHIC": {
|
||||
name: "Mono PSYCHIC",
|
||||
},
|
||||
"MONO_ICE": {
|
||||
name: "Mono ICE",
|
||||
},
|
||||
"MONO_DRAGON": {
|
||||
name: "Mono DRAGON",
|
||||
},
|
||||
"MONO_DARK": {
|
||||
name: "It's just a phase",
|
||||
},
|
||||
"MONO_FAIRY": {
|
||||
name: "Mono FAIRY",
|
||||
},
|
||||
} as const;
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"start": "Start",
|
||||
"illegalEvolution": "{{pokemon}} changed into an ineligble pokemon\nfor this challenge!",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const enConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const esConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const frConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const itConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const koConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const ptBrConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const zhCnConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { SimpleTranslationEntries } from "#app/plugins/i18n";
|
||||
|
||||
export const challenges: SimpleTranslationEntries = {
|
||||
"title": "Challenge Modifiers",
|
||||
"points": "Bad Ideas",
|
||||
"confirm_start": "Proceed with these challenges?",
|
||||
"singleGeneration.name": "Mono Gen",
|
||||
"singleGeneration.value.0": "Off",
|
||||
"singleGeneration.desc.0": "You can only use pokemon from the chosen generation.",
|
||||
"singleGeneration.value.1": "Gen 1",
|
||||
"singleGeneration.desc.1": "You can only use pokemon from generation one.",
|
||||
"singleGeneration.value.2": "Gen 2",
|
||||
"singleGeneration.desc.2": "You can only use pokemon from generation two.",
|
||||
"singleGeneration.value.3": "Gen 3",
|
||||
"singleGeneration.desc.3": "You can only use pokemon from generation three.",
|
||||
"singleGeneration.value.4": "Gen 4",
|
||||
"singleGeneration.desc.4": "You can only use pokemon from generation four.",
|
||||
"singleGeneration.value.5": "Gen 5",
|
||||
"singleGeneration.desc.5": "You can only use pokemon from generation five.",
|
||||
"singleGeneration.value.6": "Gen 6",
|
||||
"singleGeneration.desc.6": "You can only use pokemon from generation six.",
|
||||
"singleGeneration.value.7": "Gen 7",
|
||||
"singleGeneration.desc.7": "You can only use pokemon from generation seven.",
|
||||
"singleGeneration.value.8": "Gen 8",
|
||||
"singleGeneration.desc.8": "You can only use pokemon from generation eight.",
|
||||
"singleGeneration.value.9": "Gen 9",
|
||||
"singleGeneration.desc.9": "You can only use pokemon from generation nine.",
|
||||
"singleType.name": "Mono Type",
|
||||
"singleType.value.0": "Off",
|
||||
"singleType.desc.0": "You can only use pokemon of the chosen type.",
|
||||
"singleType.value.1": "Normal",
|
||||
"singleType.desc.1": "You can only use pokemon with the Normal type.",
|
||||
"singleType.value.2": "Fighting",
|
||||
"singleType.desc.2": "You can only use pokemon with the Fighting type.",
|
||||
"singleType.value.3": "Flying",
|
||||
"singleType.desc.3": "You can only use pokemon with the Flying type.",
|
||||
"singleType.value.4": "Poison",
|
||||
"singleType.desc.4": "You can only use pokemon with the Poison type.",
|
||||
"singleType.value.5": "Ground",
|
||||
"singleType.desc.5": "You can only use pokemon with the Ground type.",
|
||||
"singleType.value.6": "Rock",
|
||||
"singleType.desc.6": "You can only use pokemon with the Rock type.",
|
||||
"singleType.value.7": "Bug",
|
||||
"singleType.desc.7": "You can only use pokemon with the Bug type.",
|
||||
"singleType.value.8": "Ghost",
|
||||
"singleType.desc.8": "You can only use pokemon with the Ghost type.",
|
||||
"singleType.value.9": "Steel",
|
||||
"singleType.desc.9": "You can only use pokemon with the Steel type.",
|
||||
"singleType.value.10": "Fire",
|
||||
"singleType.desc.10": "You can only use pokemon with the Fire type.",
|
||||
"singleType.value.11": "Water",
|
||||
"singleType.desc.11": "You can only use pokemon with the Water type.",
|
||||
"singleType.value.12": "Grass",
|
||||
"singleType.desc.12": "You can only use pokemon with the Grass type.",
|
||||
"singleType.value.13": "Electric",
|
||||
"singleType.desc.13": "You can only use pokemon with the Electric type.",
|
||||
"singleType.value.14": "Psychic",
|
||||
"singleType.desc.14": "You can only use pokemon with the Psychic type.",
|
||||
"singleType.value.15": "Ice",
|
||||
"singleType.desc.15": "You can only use pokemon with the Ice type.",
|
||||
"singleType.value.16": "Dragon",
|
||||
"singleType.desc.16": "You can only use pokemon with the Dragon type.",
|
||||
"singleType.value.17": "Dark",
|
||||
"singleType.desc.17": "You can only use pokemon with the Dark type.",
|
||||
"singleType.value.18": "Fairy",
|
||||
"singleType.desc.18": "You can only use pokemon with the Fairy type.",
|
||||
} as const;
|
|
@ -5,6 +5,7 @@ import { battle } from "./battle";
|
|||
import { battleMessageUiHandler } from "./battle-message-ui-handler";
|
||||
import { berry } from "./berry";
|
||||
import { biome } from "./biome";
|
||||
import { challenges } from "./challenges";
|
||||
import { commandUiHandler } from "./command-ui-handler";
|
||||
import {
|
||||
PGFbattleSpecDialogue,
|
||||
|
@ -45,6 +46,7 @@ export const zhTwConfig = {
|
|||
battleMessageUiHandler: battleMessageUiHandler,
|
||||
berry: berry,
|
||||
biome: biome,
|
||||
challenges: challenges,
|
||||
commandUiHandler: commandUiHandler,
|
||||
PGMdialogue: PGMdialogue,
|
||||
PGFdialogue: PGFdialogue,
|
||||
|
|
154
src/phases.ts
154
src/phases.ts
|
@ -36,7 +36,7 @@ import { getBiomeKey } from "./field/arena";
|
|||
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
||||
import { BattleSpec } from "./enums/battle-spec";
|
||||
import { Species } from "./data/enums/species";
|
||||
import { HealAchv, LevelAchv, achvs } from "./system/achv";
|
||||
import { ChallengeAchv, HealAchv, LevelAchv, achvs } from "./system/achv";
|
||||
import { TrainerSlot, trainerConfigs } from "./data/trainer-config";
|
||||
import { TrainerType } from "./data/enums/trainer-type";
|
||||
import { EggHatchPhase } from "./egg-hatch-phase";
|
||||
|
@ -55,7 +55,7 @@ import { TerrainType } from "./data/terrain";
|
|||
import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select-ui-handler";
|
||||
import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler";
|
||||
import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run";
|
||||
import { GameModes, gameModes } from "./game-mode";
|
||||
import { GameMode, GameModes, getGameMode } from "./game-mode";
|
||||
import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./data/pokemon-species";
|
||||
import i18next from "./plugins/i18n";
|
||||
import { Abilities } from "./data/enums/abilities";
|
||||
|
@ -202,14 +202,21 @@ export class TitlePhase extends Phase {
|
|||
if (this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]) {
|
||||
const options: OptionSelectItem[] = [
|
||||
{
|
||||
label: gameModes[GameModes.CLASSIC].getName(),
|
||||
label: GameMode.getModeName(GameModes.CLASSIC),
|
||||
handler: () => {
|
||||
setModeAndEnd(GameModes.CLASSIC);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: gameModes[GameModes.ENDLESS].getName(),
|
||||
label: GameMode.getModeName(GameModes.CHALLENGE),
|
||||
handler: () => {
|
||||
setModeAndEnd(GameModes.CHALLENGE);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: GameMode.getModeName(GameModes.ENDLESS),
|
||||
handler: () => {
|
||||
setModeAndEnd(GameModes.ENDLESS);
|
||||
return true;
|
||||
|
@ -218,7 +225,7 @@ export class TitlePhase extends Phase {
|
|||
];
|
||||
if (this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]) {
|
||||
options.push({
|
||||
label: gameModes[GameModes.SPLICED_ENDLESS].getName(),
|
||||
label: GameMode.getModeName(GameModes.SPLICED_ENDLESS),
|
||||
handler: () => {
|
||||
setModeAndEnd(GameModes.SPLICED_ENDLESS);
|
||||
return true;
|
||||
|
@ -307,7 +314,7 @@ export class TitlePhase extends Phase {
|
|||
this.scene.sessionSlotId = slotId;
|
||||
|
||||
const generateDaily = (seed: string) => {
|
||||
this.scene.gameMode = gameModes[GameModes.DAILY];
|
||||
this.scene.gameMode = getGameMode(GameModes.DAILY);
|
||||
|
||||
this.scene.setSeed(seed);
|
||||
this.scene.resetSeed(1);
|
||||
|
@ -369,7 +376,12 @@ export class TitlePhase extends Phase {
|
|||
end(): void {
|
||||
if (!this.loaded && !this.scene.gameMode.isDaily) {
|
||||
this.scene.arena.preloadBgm();
|
||||
this.scene.pushPhase(new SelectStarterPhase(this.scene, this.gameMode));
|
||||
this.scene.gameMode = getGameMode(this.gameMode);
|
||||
if (this.gameMode === GameModes.CHALLENGE) {
|
||||
this.scene.pushPhase(new SelectChallengePhase(this.scene));
|
||||
} else {
|
||||
this.scene.pushPhase(new SelectStarterPhase(this.scene));
|
||||
}
|
||||
this.scene.newArena(this.scene.gameMode.getStartingBiome(this.scene));
|
||||
} else {
|
||||
this.scene.playBgm();
|
||||
|
@ -378,7 +390,7 @@ export class TitlePhase extends Phase {
|
|||
this.scene.pushPhase(new EncounterPhase(this.scene, this.loaded));
|
||||
|
||||
if (this.loaded) {
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()).length;
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle()).length;
|
||||
|
||||
this.scene.pushPhase(new SummonPhase(this.scene, 0, true, true));
|
||||
if (this.scene.currentBattle.double && availablePartyMembers > 1) {
|
||||
|
@ -504,13 +516,24 @@ export class SelectGenderPhase extends Phase {
|
|||
}
|
||||
}
|
||||
|
||||
export class SelectStarterPhase extends Phase {
|
||||
private gameMode: GameModes;
|
||||
|
||||
constructor(scene: BattleScene, gameMode: GameModes) {
|
||||
export class SelectChallengePhase extends Phase {
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
}
|
||||
|
||||
this.gameMode = gameMode;
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
this.scene.playBgm("menu");
|
||||
|
||||
this.scene.ui.setMode(Mode.CHALLENGE_SELECT);
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectStarterPhase extends Phase {
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
}
|
||||
|
||||
start() {
|
||||
|
@ -529,7 +552,7 @@ export class SelectStarterPhase extends Phase {
|
|||
this.scene.sessionSlotId = slotId;
|
||||
this.initBattle(starters);
|
||||
});
|
||||
}, this.gameMode);
|
||||
});
|
||||
}
|
||||
|
||||
initBattle(starters: Starter[]) {
|
||||
|
@ -1002,7 +1025,7 @@ export class EncounterPhase extends BattlePhase {
|
|||
}
|
||||
|
||||
if (!this.loaded) {
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted());
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle());
|
||||
|
||||
if (!availablePartyMembers[0].isOnField()) {
|
||||
this.scene.pushPhase(new SummonPhase(this.scene, 0));
|
||||
|
@ -1295,20 +1318,29 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||
*/
|
||||
preSummon(): void {
|
||||
const partyMember = this.getPokemon();
|
||||
// If the Pokemon about to be sent out is fainted, switch to the first non-fainted Pokemon
|
||||
if (partyMember.isFainted()) {
|
||||
console.warn("The Pokemon about to be sent out is fainted. Attempting to resolve...");
|
||||
// If the Pokemon about to be sent out is fainted or illegal under a challenge, switch to the first non-fainted legal Pokemon
|
||||
if (!partyMember.isAllowedInBattle()) {
|
||||
console.warn("The Pokemon about to be sent out is fainted or illegal under a challenge. Attempting to resolve...");
|
||||
|
||||
// First check if they're somehow still in play, if so remove them.
|
||||
if (partyMember.isOnField()) {
|
||||
partyMember.hideInfo();
|
||||
partyMember.setVisible(false);
|
||||
this.scene.field.remove(partyMember);
|
||||
this.scene.triggerPokemonFormChange(partyMember, SpeciesFormChangeActiveTrigger, true);
|
||||
}
|
||||
|
||||
const party = this.getParty();
|
||||
|
||||
// Find the first non-fainted Pokemon index above the current one
|
||||
const nonFaintedIndex = party.findIndex((p, i) => i > this.partyMemberIndex && !p.isFainted());
|
||||
if (nonFaintedIndex === -1) {
|
||||
const legalIndex = party.findIndex((p, i) => i > this.partyMemberIndex && p.isAllowedInBattle());
|
||||
if (legalIndex === -1) {
|
||||
console.error("Party Details:\n", party);
|
||||
throw new Error("All available Pokemon were fainted!");
|
||||
throw new Error("All available Pokemon were fainted or illegal!");
|
||||
}
|
||||
|
||||
// Swaps the fainted Pokemon and the first non-fainted Pokemon in the party
|
||||
[party[this.partyMemberIndex], party[nonFaintedIndex]] = [party[nonFaintedIndex], party[this.partyMemberIndex]];
|
||||
// Swaps the fainted Pokemon and the first non-fainted legal Pokemon in the party
|
||||
[party[this.partyMemberIndex], party[legalIndex]] = [party[legalIndex], party[this.partyMemberIndex]];
|
||||
console.warn("Swapped %s %O with %s %O", partyMember?.name, partyMember, party[0]?.name, party[0]);
|
||||
}
|
||||
|
||||
|
@ -1352,7 +1384,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||
if (this.fieldIndex === 1) {
|
||||
pokemon.setFieldPosition(FieldPosition.RIGHT, 0);
|
||||
} else {
|
||||
const availablePartyMembers = this.getParty().filter(p => !p.isFainted()).length;
|
||||
const availablePartyMembers = this.getParty().filter(p => p.isAllowedInBattle()).length;
|
||||
pokemon.setFieldPosition(!this.scene.currentBattle.double || availablePartyMembers === 1 ? FieldPosition.CENTER : FieldPosition.LEFT);
|
||||
}
|
||||
|
||||
|
@ -1642,7 +1674,7 @@ export class ToggleDoublePositionPhase extends BattlePhase {
|
|||
|
||||
const playerPokemon = this.scene.getPlayerField().find(p => p.isActive(true));
|
||||
if (playerPokemon) {
|
||||
playerPokemon.setFieldPosition(this.double && this.scene.getParty().filter(p => !p.isFainted()).length > 1 ? FieldPosition.LEFT : FieldPosition.CENTER, 500).then(() => {
|
||||
playerPokemon.setFieldPosition(this.double && this.scene.getParty().filter(p => p.isAllowedInBattle()).length > 1 ? FieldPosition.LEFT : FieldPosition.CENTER, 500).then(() => {
|
||||
if (playerPokemon.getFieldIndex() === 1) {
|
||||
const party = this.scene.getParty();
|
||||
party[1] = party[0];
|
||||
|
@ -1742,6 +1774,34 @@ export class TurnInitPhase extends FieldPhase {
|
|||
start() {
|
||||
super.start();
|
||||
|
||||
this.scene.getPlayerField().forEach(p => {
|
||||
// If this pokemon is in play and evolved into something illegal under the current challenge, force a switch
|
||||
if (p.isOnField() && !p.isAllowedInBattle()) {
|
||||
this.scene.queueMessage(i18next.t("challenges:illegalEvolution", {"pokemon": p.name}), null, true);
|
||||
|
||||
const allowedPokemon = this.scene.getParty().filter(p => p.isAllowedInBattle());
|
||||
|
||||
if (!allowedPokemon.length) {
|
||||
// If there are no longer any legal pokemon in the party, game over.
|
||||
this.scene.clearPhaseQueue();
|
||||
this.scene.unshiftPhase(new GameOverPhase(this.scene));
|
||||
} else if (allowedPokemon.length >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !allowedPokemon[0].isActive(true))) {
|
||||
// If there is at least one pokemon in the back that is legal to switch in, force a switch.
|
||||
p.switchOut(false, true);
|
||||
} else {
|
||||
// If there are no pokemon in the back but we're not game overing, just hide the pokemon.
|
||||
// This should only happen in double battles.
|
||||
p.hideInfo();
|
||||
p.setVisible(false);
|
||||
this.scene.field.remove(p);
|
||||
this.scene.triggerPokemonFormChange(p, SpeciesFormChangeActiveTrigger, true);
|
||||
}
|
||||
if (allowedPokemon.length === 1 && this.scene.currentBattle.double) {
|
||||
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//this.scene.pushPhase(new MoveAnimTestPhase(this.scene));
|
||||
this.scene.eventTarget.dispatchEvent(new TurnInitEvent());
|
||||
|
||||
|
@ -1776,11 +1836,17 @@ export class CommandPhase extends FieldPhase {
|
|||
super.start();
|
||||
|
||||
if (this.fieldIndex) {
|
||||
// If we somehow are attempting to check the right pokemon but there's only one pokemon out
|
||||
// Switch back to the center pokemon. This can happen rarely in double battles with mid turn switching
|
||||
if (this.scene.getPlayerField().filter(p => p.isActive()).length === 1) {
|
||||
this.fieldIndex = FieldPosition.CENTER;
|
||||
} else {
|
||||
const allyCommand = this.scene.currentBattle.turnCommands[this.fieldIndex - 1];
|
||||
if (allyCommand.command === Command.BALL || allyCommand.command === Command.RUN) {
|
||||
this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: allyCommand.command, skip: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.scene.currentBattle.turnCommands[this.fieldIndex]?.skip) {
|
||||
return this.end();
|
||||
|
@ -2353,7 +2419,7 @@ export class BattleEndPhase extends BattlePhase {
|
|||
}
|
||||
}
|
||||
|
||||
for (const pokemon of this.scene.getParty().filter(p => !p.isFainted())) {
|
||||
for (const pokemon of this.scene.getParty().filter(p => p.isAllowedInBattle())) {
|
||||
applyPostBattleAbAttrs(PostBattleAbAttr, pokemon);
|
||||
}
|
||||
|
||||
|
@ -3486,7 +3552,7 @@ export class DamagePhase extends PokemonPhase {
|
|||
this.scene.setFieldScale(0.75);
|
||||
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
||||
this.scene.currentBattle.double = true;
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted());
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle());
|
||||
if (availablePartyMembers.length > 1) {
|
||||
this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, true));
|
||||
if (!availablePartyMembers[1].isOnField()) {
|
||||
|
@ -3568,11 +3634,11 @@ export class FaintPhase extends PokemonPhase {
|
|||
}
|
||||
|
||||
if (this.player) {
|
||||
const nonFaintedPartyMembers = this.scene.getParty().filter(p => !p.isFainted());
|
||||
const nonFaintedPartyMemberCount = nonFaintedPartyMembers.length;
|
||||
const nonFaintedLegalPartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle());
|
||||
const nonFaintedPartyMemberCount = nonFaintedLegalPartyMembers.length;
|
||||
if (!nonFaintedPartyMemberCount) {
|
||||
this.scene.unshiftPhase(new GameOverPhase(this.scene));
|
||||
} else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !nonFaintedPartyMembers[0].isActive(true))) {
|
||||
} else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !nonFaintedLegalPartyMembers[0].isActive(true))) {
|
||||
this.scene.pushPhase(new SwitchPhase(this.scene, this.fieldIndex, true, false));
|
||||
}
|
||||
if (nonFaintedPartyMemberCount === 1 && this.scene.currentBattle.double) {
|
||||
|
@ -3966,7 +4032,7 @@ export class GameOverPhase extends BattlePhase {
|
|||
this.scene.gameData.loadSession(this.scene, this.scene.sessionSlotId).then(() => {
|
||||
this.scene.pushPhase(new EncounterPhase(this.scene, true));
|
||||
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()).length;
|
||||
const availablePartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle()).length;
|
||||
|
||||
this.scene.pushPhase(new SummonPhase(this.scene, 0));
|
||||
if (this.scene.currentBattle.double && availablePartyMembers > 1) {
|
||||
|
@ -4018,6 +4084,10 @@ export class GameOverPhase extends BattlePhase {
|
|||
this.scene.clearPhaseQueue();
|
||||
this.scene.ui.clearText();
|
||||
|
||||
if (this.victory && this.scene.gameMode.isChallenge) {
|
||||
this.scene.gameMode.challenges.forEach(c => this.scene.validateAchvs(ChallengeAchv, c));
|
||||
}
|
||||
|
||||
const clear = (endCardPhase?: EndCardPhase) => {
|
||||
if (newClear) {
|
||||
this.handleUnlocks();
|
||||
|
@ -4221,17 +4291,17 @@ export class SwitchPhase extends BattlePhase {
|
|||
super.start();
|
||||
|
||||
// Skip modal switch if impossible
|
||||
if (this.isModal && !this.scene.getParty().filter(p => !p.isFainted() && !p.isActive(true)).length) {
|
||||
if (this.isModal && !this.scene.getParty().filter(p => !p.isAllowedInBattle() && !p.isActive(true)).length) {
|
||||
return super.end();
|
||||
}
|
||||
|
||||
// Check if there is any space still in field
|
||||
if (this.isModal && this.scene.getPlayerField().filter(p => !p.isFainted() && p.isActive(true)).length >= this.scene.currentBattle.getBattlerCount()) {
|
||||
if (this.isModal && this.scene.getPlayerField().filter(p => !p.isAllowedInBattle() && p.isActive(true)).length >= this.scene.currentBattle.getBattlerCount()) {
|
||||
return super.end();
|
||||
}
|
||||
|
||||
// Override field index to 0 in case of double battle where 2/3 remaining party members fainted at once
|
||||
const fieldIndex = this.scene.currentBattle.getBattlerCount() === 1 || this.scene.getParty().filter(p => !p.isFainted()).length > 1 ? this.fieldIndex : 0;
|
||||
// Override field index to 0 in case of double battle where 2/3 remaining legal party members fainted at once
|
||||
const fieldIndex = this.scene.currentBattle.getBattlerCount() === 1 || this.scene.getParty().filter(p => p.isAllowedInBattle()).length > 1 ? this.fieldIndex : 0;
|
||||
|
||||
this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, fieldIndex, (slotIndex: integer, option: PartyOption) => {
|
||||
if (slotIndex >= this.scene.currentBattle.getBattlerCount() && slotIndex < 6) {
|
||||
|
@ -4917,7 +4987,8 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
let cost: integer;
|
||||
switch (rowCursor) {
|
||||
case 0:
|
||||
if (!cursor) {
|
||||
switch (cursor) {
|
||||
case 0:
|
||||
const rerollCost = this.getRerollCost(typeOptions, this.scene.lockModifierTiers);
|
||||
if (this.scene.money < rerollCost) {
|
||||
this.scene.ui.playError();
|
||||
|
@ -4932,7 +5003,8 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
this.scene.animateMoneyChanged(false);
|
||||
this.scene.playSound("buy");
|
||||
}
|
||||
} else if (cursor === 1) {
|
||||
break;
|
||||
case 1:
|
||||
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => {
|
||||
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
|
||||
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
|
@ -4943,7 +5015,13 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers));
|
||||
}
|
||||
}, PartyUiHandler.FilterItemMaxStacks);
|
||||
} else {
|
||||
break;
|
||||
case 2:
|
||||
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.CHECK, -1, () => {
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers));
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
this.scene.lockModifierTiers = !this.scene.lockModifierTiers;
|
||||
const uiHandler = this.scene.ui.getHandler() as ModifierSelectUiHandler;
|
||||
uiHandler.setRerollCost(this.getRerollCost(typeOptions, this.scene.lockModifierTiers));
|
||||
|
|
|
@ -222,6 +222,7 @@ declare module "i18next" {
|
|||
berry: BerryTranslationEntries;
|
||||
achv: AchievementTranslationEntries;
|
||||
gameStatsUiHandler: SimpleTranslationEntries;
|
||||
challenges: SimpleTranslationEntries;
|
||||
voucher: SimpleTranslationEntries;
|
||||
biome: SimpleTranslationEntries;
|
||||
pokemonInfoContainer: SimpleTranslationEntries;
|
||||
|
|
|
@ -3,6 +3,7 @@ import BattleScene from "../battle-scene";
|
|||
import { TurnHeldItemTransferModifier } from "../modifier/modifier";
|
||||
import i18next from "../plugins/i18n";
|
||||
import * as Utils from "../utils";
|
||||
import { Challenge, SingleGenerationChallenge, SingleTypeChallenge } from "#app/data/challenge.js";
|
||||
|
||||
export enum AchvTier {
|
||||
COMMON,
|
||||
|
@ -126,6 +127,12 @@ export class ModifierAchv extends Achv {
|
|||
}
|
||||
}
|
||||
|
||||
export class ChallengeAchv extends Achv {
|
||||
constructor(localizationKey: string, name: string, description: string, iconImage: string, score: integer, challengeFunc: (challenge: Challenge) => boolean) {
|
||||
super(localizationKey, name, description, iconImage, score, (_scene: BattleScene, args: any[]) => challengeFunc((args[0] as Challenge)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the description of an achievement from the localization file with all the necessary variables filled in
|
||||
|
@ -214,6 +221,43 @@ export function getAchievementDescription(localizationKey: string): string {
|
|||
return i18next.t("achv:PERFECT_IVS.description");
|
||||
case "CLASSIC_VICTORY":
|
||||
return i18next.t("achv:CLASSIC_VICTORY.description");
|
||||
case "MONO_GEN_ONE":
|
||||
return i18next.t("achv:MONO_GEN_ONE.description");
|
||||
case "MONO_GEN_TWO":
|
||||
return i18next.t("achv:MONO_GEN_TWO.description");
|
||||
case "MONO_GEN_THREE":
|
||||
return i18next.t("achv:MONO_GEN_THREE.description");
|
||||
case "MONO_GEN_FOUR":
|
||||
return i18next.t("achv:MONO_GEN_FOUR.description");
|
||||
case "MONO_GEN_FIVE":
|
||||
return i18next.t("achv:MONO_GEN_FIVE.description");
|
||||
case "MONO_GEN_SIX":
|
||||
return i18next.t("achv:MONO_GEN_SIX.description");
|
||||
case "MONO_GEN_SEVEN":
|
||||
return i18next.t("achv:MONO_GEN_SEVEN.description");
|
||||
case "MONO_GEN_EIGHT":
|
||||
return i18next.t("achv:MONO_GEN_EIGHT.description");
|
||||
case "MONO_GEN_NINE":
|
||||
return i18next.t("achv:MONO_GEN_NINE.description");
|
||||
case "MONO_NORMAL":
|
||||
case "MONO_FIGHTING":
|
||||
case "MONO_FLYING":
|
||||
case "MONO_POISON":
|
||||
case "MONO_GROUND":
|
||||
case "MONO_ROCK":
|
||||
case "MONO_BUG":
|
||||
case "MONO_GHOST":
|
||||
case "MONO_STEEL":
|
||||
case "MONO_FIRE":
|
||||
case "MONO_WATER":
|
||||
case "MONO_GRASS":
|
||||
case "MONO_ELECTRIC":
|
||||
case "MONO_PSYCHIC":
|
||||
case "MONO_ICE":
|
||||
case "MONO_DRAGON":
|
||||
case "MONO_DARK":
|
||||
case "MONO_FAIRY":
|
||||
return i18next.t("achv:MonoType.description", {"type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`)});
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
@ -261,6 +305,33 @@ export const achvs = {
|
|||
HIDDEN_ABILITY: new Achv("HIDDEN_ABILITY","", "HIDDEN_ABILITY.description", "ability_charm", 75),
|
||||
PERFECT_IVS: new Achv("PERFECT_IVS","", "PERFECT_IVS.description", "blunder_policy", 100),
|
||||
CLASSIC_VICTORY: new Achv("CLASSIC_VICTORY","", "CLASSIC_VICTORY.description", "relic_crown", 150),
|
||||
MONO_GEN_ONE_VICTORY: new ChallengeAchv("MONO_GEN_ONE","", "MONO_GEN_ONE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 1),
|
||||
MONO_GEN_TWO_VICTORY: new ChallengeAchv("MONO_GEN_TWO","", "MONO_GEN_TWO.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 2),
|
||||
MONO_GEN_THREE_VICTORY: new ChallengeAchv("MONO_GEN_THREE","", "MONO_GEN_THREE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 3),
|
||||
MONO_GEN_FOUR_VICTORY: new ChallengeAchv("MONO_GEN_FOUR","", "MONO_GEN_FOUR.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 4),
|
||||
MONO_GEN_FIVE_VICTORY: new ChallengeAchv("MONO_GEN_FIVE","", "MONO_GEN_FIVE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 5),
|
||||
MONO_GEN_SIX_VICTORY: new ChallengeAchv("MONO_GEN_SIX","", "MONO_GEN_SIX.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 6),
|
||||
MONO_GEN_SEVEN_VICTORY: new ChallengeAchv("MONO_GEN_SEVEN","", "MONO_GEN_SEVEN.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 7),
|
||||
MONO_GEN_EIGHT_VICTORY: new ChallengeAchv("MONO_GEN_EIGHT","", "MONO_GEN_EIGHT.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 8),
|
||||
MONO_GEN_NINE_VICTORY: new ChallengeAchv("MONO_GEN_NINE","", "MONO_GEN_NINE.description", "mystic_ticket", 100, c => c instanceof SingleGenerationChallenge && c.value === 9),
|
||||
MONO_NORMAL: new ChallengeAchv("MONO_NORMAL","", "MONO_NORMAL.description", "silk_scarf", 100, c => c instanceof SingleTypeChallenge && c.value === 1),
|
||||
MONO_FIGHTING: new ChallengeAchv("MONO_FIGHTING","", "MONO_FIGHTING.description", "black_belt", 100, c => c instanceof SingleTypeChallenge && c.value === 2),
|
||||
MONO_FLYING: new ChallengeAchv("MONO_FLYING","", "MONO_FLYING.description", "sharp_beak", 100, c => c instanceof SingleTypeChallenge && c.value === 3),
|
||||
MONO_POISON: new ChallengeAchv("MONO_POISON","", "MONO_POISON.description", "poison_barb", 100, c => c instanceof SingleTypeChallenge && c.value === 4),
|
||||
MONO_GROUND: new ChallengeAchv("MONO_GROUND","", "MONO_GROUND.description", "soft_sand", 100, c => c instanceof SingleTypeChallenge && c.value === 5),
|
||||
MONO_ROCK: new ChallengeAchv("MONO_ROCK","", "MONO_ROCK.description", "hard_stone", 100, c => c instanceof SingleTypeChallenge && c.value === 6),
|
||||
MONO_BUG: new ChallengeAchv("MONO_BUG","", "MONO_BUG.description", "silver_powder", 100, c => c instanceof SingleTypeChallenge && c.value === 7),
|
||||
MONO_GHOST: new ChallengeAchv("MONO_GHOST","", "MONO_GHOST.description", "spell_tag", 100, c => c instanceof SingleTypeChallenge && c.value === 8),
|
||||
MONO_STEEL: new ChallengeAchv("MONO_STEEL","", "MONO_STEEL.description", "metal_coat", 100, c => c instanceof SingleTypeChallenge && c.value === 9),
|
||||
MONO_FIRE: new ChallengeAchv("MONO_FIRE","", "MONO_FIRE.description", "charcoal", 100, c => c instanceof SingleTypeChallenge && c.value === 10),
|
||||
MONO_WATER: new ChallengeAchv("MONO_WATER","", "MONO_WATER.description", "mystic_water", 100, c => c instanceof SingleTypeChallenge && c.value === 11),
|
||||
MONO_GRASS: new ChallengeAchv("MONO_GRASS","", "MONO_GRASS.description", "miracle_seed", 100, c => c instanceof SingleTypeChallenge && c.value === 12),
|
||||
MONO_ELECTRIC: new ChallengeAchv("MONO_ELECTRIC","", "MONO_ELECTRIC.description", "magnet", 100, c => c instanceof SingleTypeChallenge && c.value === 13),
|
||||
MONO_PSYCHIC: new ChallengeAchv("MONO_PSYCHIC","", "MONO_PSYCHIC.description", "twisted_spoon", 100, c => c instanceof SingleTypeChallenge && c.value === 14),
|
||||
MONO_ICE: new ChallengeAchv("MONO_ICE","", "MONO_ICE.description", "never_melt_ice", 100, c => c instanceof SingleTypeChallenge && c.value === 15),
|
||||
MONO_DRAGON: new ChallengeAchv("MONO_DRAGON","", "MONO_DRAGON.description", "dragon_fang", 100, c => c instanceof SingleTypeChallenge && c.value === 16),
|
||||
MONO_DARK: new ChallengeAchv("MONO_DARK","", "MONO_DARK.description", "black_glasses", 100, c => c instanceof SingleTypeChallenge && c.value === 17),
|
||||
MONO_FAIRY: new ChallengeAchv("MONO_FAIRY","", "MONO_FAIRY.description", "fairy_feather", 100, c => c instanceof SingleTypeChallenge && c.value === 18),
|
||||
};
|
||||
|
||||
export function initAchievements() {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { Challenge, copyChallenge } from "#app/data/challenge.js";
|
||||
|
||||
export default class ChallengeData {
|
||||
public id: integer;
|
||||
public value: integer;
|
||||
public severity: integer;
|
||||
|
||||
constructor(source: Challenge | any) {
|
||||
this.id = source.id;
|
||||
this.value = source.value;
|
||||
this.severity = source.severity;
|
||||
}
|
||||
|
||||
toChallenge(): Challenge {
|
||||
return copyChallenge(this);
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ import PokemonData from "./pokemon-data";
|
|||
import PersistentModifierData from "./modifier-data";
|
||||
import ArenaData from "./arena-data";
|
||||
import { Unlockables } from "./unlockables";
|
||||
import { GameModes, gameModes } from "../game-mode";
|
||||
import { GameModes, getGameMode } from "../game-mode";
|
||||
import { BattleType } from "../battle";
|
||||
import TrainerData from "./trainer-data";
|
||||
import { trainerConfigs } from "../data/trainer-config";
|
||||
|
@ -38,6 +38,7 @@ import { EnemyAttackStatusEffectChanceModifier } from "../modifier/modifier";
|
|||
import { StatusEffect } from "#app/data/status-effect.js";
|
||||
import { PlayerGender } from "#app/data/enums/player-gender";
|
||||
import { GameDataType } from "#app/data/enums/game-data-type";
|
||||
import ChallengeData from "./challenge-data";
|
||||
|
||||
const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary
|
||||
|
||||
|
@ -107,6 +108,7 @@ export interface SessionSaveData {
|
|||
trainer: TrainerData;
|
||||
gameVersion: string;
|
||||
timestamp: integer;
|
||||
challenges: ChallengeData[];
|
||||
}
|
||||
|
||||
interface Unlocks {
|
||||
|
@ -780,7 +782,8 @@ export class GameData {
|
|||
battleType: scene.currentBattle.battleType,
|
||||
trainer: scene.currentBattle.battleType === BattleType.TRAINER ? new TrainerData(scene.currentBattle.trainer) : null,
|
||||
gameVersion: scene.game.config.gameVersion,
|
||||
timestamp: new Date().getTime()
|
||||
timestamp: new Date().getTime(),
|
||||
challenges: scene.gameMode.challenges.map(c => new ChallengeData(c))
|
||||
} as SessionSaveData;
|
||||
}
|
||||
|
||||
|
@ -829,7 +832,10 @@ export class GameData {
|
|||
const initSessionFromData = async sessionData => {
|
||||
console.debug(sessionData);
|
||||
|
||||
scene.gameMode = gameModes[sessionData.gameMode || GameModes.CLASSIC];
|
||||
scene.gameMode = getGameMode(sessionData.gameMode || GameModes.CLASSIC);
|
||||
if (sessionData.challenges) {
|
||||
scene.gameMode.challenges = sessionData.challenges.map(c => c.toChallenge());
|
||||
}
|
||||
|
||||
scene.setSeed(sessionData.seed || scene.game.config.seed[0]);
|
||||
scene.resetSeed();
|
||||
|
@ -1075,6 +1081,17 @@ export class GameData {
|
|||
return new ArenaData(v);
|
||||
}
|
||||
|
||||
if (k === "challenges") {
|
||||
const ret: ChallengeData[] = [];
|
||||
if (v === null) {
|
||||
v = [];
|
||||
}
|
||||
for (const c of v) {
|
||||
ret.push(new ChallengeData(c));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return v;
|
||||
}) as SessionSaveData;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GameModes, gameModes } from "../game-mode";
|
||||
import { GameMode, GameModes } from "../game-mode";
|
||||
|
||||
export enum Unlockables {
|
||||
ENDLESS_MODE,
|
||||
|
@ -9,10 +9,10 @@ export enum Unlockables {
|
|||
export function getUnlockableName(unlockable: Unlockables) {
|
||||
switch (unlockable) {
|
||||
case Unlockables.ENDLESS_MODE:
|
||||
return `${gameModes[GameModes.ENDLESS].getName()} Mode`;
|
||||
return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`;
|
||||
case Unlockables.MINI_BLACK_HOLE:
|
||||
return "Mini Black Hole";
|
||||
case Unlockables.SPLICED_ENDLESS_MODE:
|
||||
return `${gameModes[GameModes.SPLICED_ENDLESS].getName()} Mode`;
|
||||
return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import GameManager from "#app/test/utils/gameManager";
|
|||
import Phaser from "phaser";
|
||||
import {allSpecies} from "#app/data/pokemon-species";
|
||||
import {PlayerGender} from "#app/data/enums/player-gender";
|
||||
import { getGameMode } from "#app/game-mode.js";
|
||||
|
||||
describe("Test Battle Phase", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
|
@ -229,8 +230,9 @@ describe("Test Battle Phase", () => {
|
|||
await game.phaseInterceptor.mustRun(SelectGenderPhase).catch((error) => expect(error).toBe(SelectGenderPhase));
|
||||
await game.phaseInterceptor.mustRun(TitlePhase).catch((error) => expect(error).toBe(TitlePhase));
|
||||
game.onNextPrompt("TitlePhase", Mode.TITLE, () => {
|
||||
game.scene.gameMode = getGameMode(GameModes.CLASSIC);
|
||||
const starters = generateStarter(game.scene);
|
||||
const selectStarterPhase = new SelectStarterPhase(game.scene, GameModes.CLASSIC);
|
||||
const selectStarterPhase = new SelectStarterPhase(game.scene);
|
||||
game.scene.pushPhase(new EncounterPhase(game.scene, false));
|
||||
selectStarterPhase.initBattle(starters);
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ import BattleScene from "#app/battle-scene.js";
|
|||
import PhaseInterceptor from "#app/test/utils/phaseInterceptor";
|
||||
import TextInterceptor from "#app/test/utils/TextInterceptor";
|
||||
import {expect} from "vitest";
|
||||
import {GameModes} from "#app/game-mode";
|
||||
import {GameModes, getGameMode} from "#app/game-mode";
|
||||
import fs from "fs";
|
||||
import { AES, enc } from "crypto-js";
|
||||
import {updateUserInfo} from "#app/account";
|
||||
|
@ -121,8 +121,9 @@ export default class GameManager {
|
|||
return new Promise(async(resolve) => {
|
||||
await this.runToTitle();
|
||||
this.onNextPrompt("TitlePhase", Mode.TITLE, () => {
|
||||
this.scene.gameMode = getGameMode(GameModes.CLASSIC);
|
||||
const starters = generateStarter(this.scene, species);
|
||||
const selectStarterPhase = new SelectStarterPhase(this.scene, GameModes.CLASSIC);
|
||||
const selectStarterPhase = new SelectStarterPhase(this.scene);
|
||||
this.scene.pushPhase(new EncounterPhase(this.scene, false));
|
||||
selectStarterPhase.initBattle(starters);
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ import {getDailyRunStarters} from "#app/data/daily-run";
|
|||
import {Gender} from "#app/data/gender";
|
||||
import {Species} from "#app/data/enums/species";
|
||||
import {Starter} from "#app/ui/starter-select-ui-handler";
|
||||
import {GameModes, gameModes} from "#app/game-mode";
|
||||
import {GameModes, getGameMode} from "#app/game-mode";
|
||||
import {getPokemonSpecies, getPokemonSpeciesForm} from "#app/data/pokemon-species";
|
||||
import {PlayerPokemon} from "#app/field/pokemon";
|
||||
|
||||
|
@ -49,7 +49,7 @@ function getTestRunStarters(scene, seed, species) {
|
|||
return getDailyRunStarters(scene, seed);
|
||||
}
|
||||
const starters: Starter[] = [];
|
||||
const startingLevel = gameModes[GameModes.CLASSIC].getStartingLevel();
|
||||
const startingLevel = getGameMode(GameModes.CLASSIC).getStartingLevel();
|
||||
|
||||
for (const specie of species) {
|
||||
const starterSpeciesForm = getPokemonSpeciesForm(specie, 0);
|
||||
|
|
|
@ -0,0 +1,330 @@
|
|||
import BattleScene from "../battle-scene";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
import UiHandler from "./ui-handler";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import {Button} from "../enums/buttons";
|
||||
import i18next from "#app/plugins/i18n.js";
|
||||
import { SelectStarterPhase, TitlePhase } from "#app/phases.js";
|
||||
import { Challenge } from "#app/data/challenge.js";
|
||||
|
||||
/**
|
||||
* Handles all the UI for choosing optional challenges.
|
||||
*/
|
||||
export default class GameChallengesUiHandler extends UiHandler {
|
||||
private challengesContainer: Phaser.GameObjects.Container;
|
||||
private valuesContainer: Phaser.GameObjects.Container;
|
||||
|
||||
private scrollCursor: integer;
|
||||
|
||||
private optionsBg: Phaser.GameObjects.NineSlice;
|
||||
|
||||
// private difficultyText: Phaser.GameObjects.Text;
|
||||
|
||||
private descriptionText: Phaser.GameObjects.Text;
|
||||
|
||||
private challengeLabels: Phaser.GameObjects.Text[];
|
||||
private challengeValueLabels: Phaser.GameObjects.Text[];
|
||||
|
||||
private cursorObj: Phaser.GameObjects.NineSlice;
|
||||
|
||||
private startCursor: Phaser.GameObjects.NineSlice;
|
||||
|
||||
constructor(scene: BattleScene, mode?: Mode) {
|
||||
super(scene, mode);
|
||||
}
|
||||
|
||||
setup() {
|
||||
const ui = this.getUi();
|
||||
|
||||
this.challengesContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
||||
|
||||
this.challengesContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
|
||||
|
||||
// TODO: Change this back to /9 when adding in difficulty
|
||||
const headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6), 24);
|
||||
headerBg.setOrigin(0, 0);
|
||||
|
||||
const headerText = addTextObject(this.scene, 0, 0, i18next.t("challenges:title"), TextStyle.SETTINGS_LABEL);
|
||||
headerText.setOrigin(0, 0);
|
||||
headerText.setPositionRelative(headerBg, 8, 4);
|
||||
|
||||
// const difficultyBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 18) - 2, 24);
|
||||
// difficultyBg.setOrigin(0, 0);
|
||||
// difficultyBg.setPositionRelative(headerBg, headerBg.width, 0);
|
||||
|
||||
// this.difficultyText = addTextObject(this.scene, 0, 0, "0", TextStyle.SETTINGS_LABEL);
|
||||
// this.difficultyText.setOrigin(0, 0);
|
||||
// this.difficultyText.setPositionRelative(difficultyBg, 8, 4);
|
||||
|
||||
// const difficultyName = addTextObject(this.scene, 0, 0, i18next.t("challenges:points"), TextStyle.SETTINGS_LABEL);
|
||||
// difficultyName.setOrigin(0, 0);
|
||||
// difficultyName.setPositionRelative(difficultyBg, difficultyBg.width - difficultyName.displayWidth - 8, 4);
|
||||
|
||||
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 9), (this.scene.game.canvas.height / 6) - headerBg.height - 2);
|
||||
this.optionsBg.setOrigin(0, 0);
|
||||
|
||||
const descriptionBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 18) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 26);
|
||||
descriptionBg.setOrigin(0, 0);
|
||||
descriptionBg.setPositionRelative(this.optionsBg, this.optionsBg.width, 0);
|
||||
|
||||
this.descriptionText = addTextObject(this.scene, 0, 0, "", TextStyle.SETTINGS_LABEL);
|
||||
this.descriptionText.setOrigin(0, 0);
|
||||
this.descriptionText.setWordWrapWidth(500, true);
|
||||
this.descriptionText.setPositionRelative(descriptionBg, 6, 4);
|
||||
|
||||
const startBg = addWindow(this.scene, 0, 0, descriptionBg.width, 24);
|
||||
startBg.setOrigin(0, 0);
|
||||
startBg.setPositionRelative(descriptionBg, 0, descriptionBg.height);
|
||||
|
||||
const startText = addTextObject(this.scene, 0, 0, i18next.t("challenges:start"), TextStyle.SETTINGS_LABEL);
|
||||
startText.setOrigin(0, 0);
|
||||
startText.setPositionRelative(startBg, 8, 4);
|
||||
|
||||
this.startCursor = this.scene.add.nineslice(0, 0, "summary_moves_cursor", null, (this.scene.game.canvas.width / 18) - 10, 16, 1, 1, 1, 1);
|
||||
this.startCursor.setOrigin(0, 0);
|
||||
this.startCursor.setPositionRelative(startBg, 4, 4);
|
||||
this.startCursor.setVisible(false);
|
||||
|
||||
this.valuesContainer = this.scene.add.container(0, 0);
|
||||
|
||||
this.challengeLabels = [];
|
||||
this.challengeValueLabels = [];
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
this.challengeLabels[i] = addTextObject(this.scene, 8, 28 + i * 16, "", TextStyle.SETTINGS_LABEL);
|
||||
this.challengeLabels[i].setOrigin(0, 0);
|
||||
|
||||
this.valuesContainer.add(this.challengeLabels[i]);
|
||||
|
||||
this.challengeValueLabels[i] = addTextObject(this.scene, 0, 28 + i * 16, "", TextStyle.SETTINGS_LABEL);
|
||||
this.challengeValueLabels[i].setPositionRelative(this.challengeLabels[i], 100, 0);
|
||||
|
||||
this.valuesContainer.add(this.challengeValueLabels[i]);
|
||||
}
|
||||
|
||||
this.challengesContainer.add(headerBg);
|
||||
this.challengesContainer.add(headerText);
|
||||
// this.challengesContainer.add(difficultyBg);
|
||||
// this.challengesContainer.add(this.difficultyText);
|
||||
// this.challengesContainer.add(difficultyName);
|
||||
this.challengesContainer.add(this.optionsBg);
|
||||
this.challengesContainer.add(descriptionBg);
|
||||
this.challengesContainer.add(this.descriptionText);
|
||||
this.challengesContainer.add(startBg);
|
||||
this.challengesContainer.add(startText);
|
||||
this.challengesContainer.add(this.startCursor);
|
||||
this.challengesContainer.add(this.valuesContainer);
|
||||
|
||||
ui.add(this.challengesContainer);
|
||||
|
||||
this.setCursor(0);
|
||||
this.setScrollCursor(0);
|
||||
|
||||
this.challengesContainer.setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
updateText(): void {
|
||||
if (this.scene.gameMode.challenges.length > 0) {
|
||||
this.descriptionText.text = this.getActiveChallenge().getDescription();
|
||||
this.descriptionText.updateText();
|
||||
}
|
||||
|
||||
// const totalDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getDifficulty(), 0);
|
||||
// const totalMinDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getMinDifficulty(), 0);
|
||||
// this.difficultyText.text = `${totalDifficulty}` + (totalMinDifficulty ? `/${totalMinDifficulty}` : "");
|
||||
// this.difficultyText.updateText();
|
||||
|
||||
for (let i = 0; i < this.challengeLabels.length; i++) {
|
||||
if (i + this.scrollCursor < this.scene.gameMode.challenges.length) {
|
||||
this.challengeLabels[i].setVisible(true);
|
||||
this.challengeValueLabels[i].setVisible(true);
|
||||
this.challengeLabels[i].text = this.scene.gameMode.challenges[i + this.scrollCursor].getName();
|
||||
this.challengeValueLabels[i].text = this.scene.gameMode.challenges[i + this.scrollCursor].getValue();
|
||||
this.challengeLabels[i].updateText();
|
||||
this.challengeValueLabels[i].updateText();
|
||||
} else {
|
||||
this.challengeLabels[i].setVisible(false);
|
||||
this.challengeValueLabels[i].setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
super.show(args);
|
||||
|
||||
this.startCursor.setVisible(false);
|
||||
this.challengesContainer.setVisible(true);
|
||||
this.setCursor(0);
|
||||
|
||||
this.updateText();
|
||||
|
||||
this.getUi().moveTo(this.challengesContainer, this.getUi().length - 1);
|
||||
|
||||
this.getUi().hideTooltip();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes input from a specified button.
|
||||
* This method handles navigation through a UI menu, including movement through menu items
|
||||
* and handling special actions like cancellation. Each button press may adjust the cursor
|
||||
* position or the menu scroll, and plays a sound effect if the action was successful.
|
||||
*
|
||||
* @param button - The button pressed by the user.
|
||||
* @returns `true` if the action associated with the button was successfully processed, `false` otherwise.
|
||||
*/
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
// Defines the maximum number of rows that can be displayed on the screen.
|
||||
const rowsToDisplay = 9;
|
||||
|
||||
let success = false;
|
||||
|
||||
if (button === Button.CANCEL) {
|
||||
if (this.startCursor.visible) {
|
||||
this.startCursor.setVisible(false);
|
||||
this.cursorObj?.setVisible(true);
|
||||
} else {
|
||||
this.scene.clearPhaseQueue();
|
||||
this.scene.pushPhase(new TitlePhase(this.scene));
|
||||
this.scene.getCurrentPhase().end();
|
||||
}
|
||||
success = true;
|
||||
} else if (button === Button.SUBMIT || button === Button.ACTION) {
|
||||
if (this.startCursor.visible) {
|
||||
const totalDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getDifficulty(), 0);
|
||||
const totalMinDifficulty = this.scene.gameMode.challenges.reduce((v, c) => v + c.getMinDifficulty(), 0);
|
||||
if (totalDifficulty >= totalMinDifficulty) {
|
||||
this.scene.unshiftPhase(new SelectStarterPhase(this.scene));
|
||||
this.scene.getCurrentPhase().end();
|
||||
success = true;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
this.startCursor.setVisible(true);
|
||||
this.cursorObj?.setVisible(false);
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (this.cursor === 0) {
|
||||
if (this.scrollCursor === 0) {
|
||||
// When at the top of the menu and pressing UP, move to the bottommost item.
|
||||
if (this.scene.gameMode.challenges.length > rowsToDisplay) { // If there are more than 9 challenges, scroll to the bottom
|
||||
// First, set the cursor to the last visible element, preparing for the scroll to the end.
|
||||
const successA = this.setCursor(rowsToDisplay - 1);
|
||||
// Then, adjust the scroll to display the bottommost elements of the menu.
|
||||
const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay);
|
||||
success = successA && successB; // success is just there to play the little validation sound effect
|
||||
} else { // If there are 9 or less challenges, just move to the bottom one
|
||||
success = this.setCursor(this.scene.gameMode.challenges.length - 1);
|
||||
}
|
||||
} else {
|
||||
success = this.setScrollCursor(this.scrollCursor - 1);
|
||||
}
|
||||
} else {
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
}
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor === rowsToDisplay - 1) {
|
||||
if (this.scrollCursor < this.scene.gameMode.challenges.length - rowsToDisplay) {
|
||||
// When at the bottom and pressing DOWN, scroll if possible.
|
||||
success = this.setScrollCursor(this.scrollCursor + 1);
|
||||
} else {
|
||||
// When at the bottom of a scrolling menu and pressing DOWN, move to the topmost item.
|
||||
// First, set the cursor to the first visible element, preparing for the scroll to the top.
|
||||
const successA = this.setCursor(0);
|
||||
// Then, adjust the scroll to display the topmost elements of the menu.
|
||||
const successB = this.setScrollCursor(0);
|
||||
success = successA && successB; // success is just there to play the little validation sound effect
|
||||
}
|
||||
} else if (this.scene.gameMode.challenges.length < rowsToDisplay && this.cursor === this.scene.gameMode.challenges.length - 1) {
|
||||
// When at the bottom of a non-scrolling menu and pressing DOWN, move to the topmost item.
|
||||
success = this.setCursor(0);
|
||||
} else {
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
}
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
// Moves the option cursor left, if possible.
|
||||
success = this.getActiveChallenge().decreaseValue();
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
// Moves the option cursor right, if possible.
|
||||
success = this.getActiveChallenge().increaseValue();
|
||||
if (success) {
|
||||
this.updateText();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Plays a select sound effect if an action was successfully processed.
|
||||
if (success) {
|
||||
ui.playSelect();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
let ret = super.setCursor(cursor);
|
||||
|
||||
if (!this.cursorObj) {
|
||||
this.cursorObj = this.scene.add.nineslice(0, 0, "summary_moves_cursor", null, (this.scene.game.canvas.width / 9) - 10, 16, 1, 1, 1, 1);
|
||||
this.cursorObj.setOrigin(0, 0);
|
||||
this.valuesContainer.add(this.cursorObj);
|
||||
}
|
||||
|
||||
ret ||= !this.cursorObj.visible;
|
||||
this.cursorObj.setVisible(true);
|
||||
|
||||
this.cursorObj.setPositionRelative(this.optionsBg, 4, 4 + (this.cursor + this.scrollCursor) * 16);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
setScrollCursor(scrollCursor: integer): boolean {
|
||||
if (scrollCursor === this.scrollCursor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.scrollCursor = scrollCursor;
|
||||
|
||||
this.setCursor(this.cursor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getActiveChallenge(): Challenge {
|
||||
return this.scene.gameMode.challenges[this.cursor + this.scrollCursor];
|
||||
}
|
||||
|
||||
clear() {
|
||||
super.clear();
|
||||
this.challengesContainer.setVisible(false);
|
||||
this.eraseCursor();
|
||||
}
|
||||
|
||||
eraseCursor() {
|
||||
if (this.cursorObj) {
|
||||
this.cursorObj.destroy();
|
||||
}
|
||||
this.cursorObj = null;
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
private rerollButtonContainer: Phaser.GameObjects.Container;
|
||||
private lockRarityButtonContainer: Phaser.GameObjects.Container;
|
||||
private transferButtonContainer: Phaser.GameObjects.Container;
|
||||
private checkButtonContainer: Phaser.GameObjects.Container;
|
||||
private rerollCostText: Phaser.GameObjects.Text;
|
||||
private lockRarityButtonText: Phaser.GameObjects.Text;
|
||||
private moveInfoOverlay : MoveInfoOverlay;
|
||||
|
@ -45,7 +46,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
this.modifierContainer = this.scene.add.container(0, 0);
|
||||
ui.add(this.modifierContainer);
|
||||
|
||||
this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 1, -64);
|
||||
this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 71, -64);
|
||||
this.transferButtonContainer.setName("container-transfer-btn");
|
||||
this.transferButtonContainer.setVisible(false);
|
||||
ui.add(this.transferButtonContainer);
|
||||
|
@ -55,6 +56,16 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
transferButtonText.setOrigin(1, 0);
|
||||
this.transferButtonContainer.add(transferButtonText);
|
||||
|
||||
this.checkButtonContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 1, -64);
|
||||
this.checkButtonContainer.setName("container-use-btn");
|
||||
this.checkButtonContainer.setVisible(false);
|
||||
ui.add(this.checkButtonContainer);
|
||||
|
||||
const checkButtonText = addTextObject(this.scene, -4, -2, "Check Team", TextStyle.PARTY);
|
||||
checkButtonText.setName("text-use-btn");
|
||||
checkButtonText.setOrigin(1, 0);
|
||||
this.checkButtonContainer.add(checkButtonText);
|
||||
|
||||
this.rerollButtonContainer = this.scene.add.container(16, -64);
|
||||
this.rerollButtonContainer.setName("container-reroll-brn");
|
||||
this.rerollButtonContainer.setVisible(false);
|
||||
|
@ -121,6 +132,9 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
this.transferButtonContainer.setVisible(false);
|
||||
this.transferButtonContainer.setAlpha(0);
|
||||
|
||||
this.checkButtonContainer.setVisible(false);
|
||||
this.checkButtonContainer.setAlpha(0);
|
||||
|
||||
this.rerollButtonContainer.setVisible(false);
|
||||
this.rerollButtonContainer.setAlpha(0);
|
||||
|
||||
|
@ -204,12 +218,14 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
}
|
||||
|
||||
this.rerollButtonContainer.setAlpha(0);
|
||||
this.checkButtonContainer.setAlpha(0);
|
||||
this.lockRarityButtonContainer.setAlpha(0);
|
||||
this.rerollButtonContainer.setVisible(true);
|
||||
this.checkButtonContainer.setVisible(true);
|
||||
this.lockRarityButtonContainer.setVisible(canLockRarities);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: [ this.rerollButtonContainer, this.lockRarityButtonContainer ],
|
||||
targets: [ this.rerollButtonContainer, this.lockRarityButtonContainer, this.checkButtonContainer ],
|
||||
alpha: 1,
|
||||
duration: 250
|
||||
});
|
||||
|
@ -267,7 +283,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (!this.rowCursor && this.cursor === 2) {
|
||||
if (this.rowCursor === 0 && this.cursor === 3) {
|
||||
success = this.setCursor(0);
|
||||
} else if (this.rowCursor < this.shopOptionsRows.length + 1) {
|
||||
success = this.setRowCursor(this.rowCursor + 1);
|
||||
|
@ -276,13 +292,29 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
case Button.DOWN:
|
||||
if (this.rowCursor) {
|
||||
success = this.setRowCursor(this.rowCursor - 1);
|
||||
} else if (this.lockRarityButtonContainer.visible && !this.cursor) {
|
||||
success = this.setCursor(2);
|
||||
} else if (this.lockRarityButtonContainer.visible && this.cursor === 0) {
|
||||
success = this.setCursor(3);
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (!this.rowCursor) {
|
||||
success = this.cursor === 1 && this.rerollButtonContainer.visible && this.setCursor(0);
|
||||
switch (this.cursor) {
|
||||
case 0:
|
||||
success = false;
|
||||
break;
|
||||
case 1:
|
||||
success = this.rerollButtonContainer.visible && this.setCursor(0);
|
||||
break;
|
||||
case 2:
|
||||
if (this.transferButtonContainer.visible) {
|
||||
success = this.setCursor(1);
|
||||
} else if (this.rerollButtonContainer.visible) {
|
||||
success = this.setCursor(0);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (this.cursor) {
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
} else if (this.rowCursor === 1 && this.rerollButtonContainer.visible) {
|
||||
|
@ -291,7 +323,21 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
break;
|
||||
case Button.RIGHT:
|
||||
if (!this.rowCursor) {
|
||||
success = this.cursor !== 1 && this.transferButtonContainer.visible && this.setCursor(1);
|
||||
switch (this.cursor) {
|
||||
case 0:
|
||||
if (this.transferButtonContainer.visible) {
|
||||
success = this.setCursor(1);
|
||||
} else {
|
||||
success = this.setCursor(2);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
success = this.setCursor(2);
|
||||
break;
|
||||
case 2:
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
} else if (this.cursor < this.getRowItems(this.rowCursor) - 1) {
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
} else if (this.rowCursor === 1 && this.transferButtonContainer.visible) {
|
||||
|
@ -337,12 +383,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
// prepare the move overlay to be shown with the toggle
|
||||
this.moveInfoOverlay.show(allMoves[type.moveId]);
|
||||
}
|
||||
} else if (!cursor) {
|
||||
} else if (cursor === 0) {
|
||||
this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? -72 : -60);
|
||||
ui.showText("Spend money to reroll your item options.");
|
||||
} else if (cursor === 1) {
|
||||
this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 50, -60);
|
||||
this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 120, -60);
|
||||
ui.showText("Transfer a held item from one Pokémon to another.");
|
||||
} else if (cursor === 2) {
|
||||
this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 60, -60);
|
||||
ui.showText("Check your team or use a form changing item.");
|
||||
} else {
|
||||
this.cursorObj.setPosition(6, -60);
|
||||
ui.showText("Lock item rarities on reroll (affects reroll cost).");
|
||||
|
@ -354,14 +403,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
setRowCursor(rowCursor: integer): boolean {
|
||||
const lastRowCursor = this.rowCursor;
|
||||
|
||||
if (rowCursor !== lastRowCursor && (rowCursor || this.rerollButtonContainer.visible || this.transferButtonContainer.visible)) {
|
||||
if (rowCursor !== lastRowCursor) {
|
||||
this.rowCursor = rowCursor;
|
||||
let newCursor = Math.round(this.cursor / Math.max(this.getRowItems(lastRowCursor) - 1, 1) * (this.getRowItems(rowCursor) - 1));
|
||||
if (!rowCursor) {
|
||||
if (!newCursor && !this.rerollButtonContainer.visible) {
|
||||
if (rowCursor === 0) {
|
||||
if (newCursor === 0 && !this.rerollButtonContainer.visible) {
|
||||
newCursor = 1;
|
||||
} else if (newCursor && !this.transferButtonContainer.visible) {
|
||||
newCursor = 0;
|
||||
}
|
||||
if (newCursor === 1 && !this.transferButtonContainer.visible) {
|
||||
newCursor = 2;
|
||||
}
|
||||
}
|
||||
this.cursor = -1;
|
||||
|
@ -375,7 +425,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
private getRowItems(rowCursor: integer): integer {
|
||||
switch (rowCursor) {
|
||||
case 0:
|
||||
return 2;
|
||||
return 3;
|
||||
case 1:
|
||||
return this.options.length;
|
||||
default:
|
||||
|
@ -437,7 +487,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
onComplete: () => options.forEach(o => o.destroy())
|
||||
});
|
||||
|
||||
[ this.rerollButtonContainer, this.transferButtonContainer, this.lockRarityButtonContainer ].forEach(container => {
|
||||
[ this.rerollButtonContainer, this.checkButtonContainer, this.transferButtonContainer, this.lockRarityButtonContainer ].forEach(container => {
|
||||
if (container.visible) {
|
||||
this.scene.tweens.add({
|
||||
targets: container,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { CommandPhase } from "../phases";
|
||||
import { CommandPhase, SelectModifierPhase } from "../phases";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { addTextObject, TextStyle } from "./text";
|
||||
|
@ -17,6 +17,7 @@ import { addWindow } from "./ui-theme";
|
|||
import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms";
|
||||
import { getVariantTint } from "#app/data/variant";
|
||||
import {Button} from "../enums/buttons";
|
||||
import { applyChallenges, ChallengeType } from "#app/data/challenge.js";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
import i18next from "i18next";
|
||||
|
||||
|
@ -33,7 +34,8 @@ export enum PartyUiMode {
|
|||
REMEMBER_MOVE_MODIFIER,
|
||||
MODIFIER_TRANSFER,
|
||||
SPLICE,
|
||||
RELEASE
|
||||
RELEASE,
|
||||
CHECK
|
||||
}
|
||||
|
||||
export enum PartyOption {
|
||||
|
@ -120,6 +122,20 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* For consistency reasons, this looks like the above filters. However this is used only internally and is always enforced for switching.
|
||||
* @param pokemon The pokemon to check.
|
||||
* @returns
|
||||
*/
|
||||
private FilterChallengeLegal = (pokemon: PlayerPokemon) => {
|
||||
const challengeAllowed = new Utils.BooleanHolder(true);
|
||||
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, pokemon, challengeAllowed);
|
||||
if (!challengeAllowed.value) {
|
||||
return `${pokemon.name} can't be used in\nthis challenge!`;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
private static FilterAllMoves = (_pokemonMove: PokemonMove) => null;
|
||||
|
||||
public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => {
|
||||
|
@ -280,6 +296,9 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
let filterResult: string;
|
||||
if (option !== PartyOption.TRANSFER && option !== PartyOption.SPLICE) {
|
||||
filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon);
|
||||
if (filterResult === null && (option === PartyOption.SEND_OUT || option === PartyOption.PASS_BATON)) {
|
||||
filterResult = this.FilterChallengeLegal(pokemon);
|
||||
}
|
||||
if (filterResult === null && this.partyUiMode === PartyUiMode.MOVE_MODIFIER) {
|
||||
filterResult = this.moveSelectFilter(pokemon.moveset[this.optionsCursor]);
|
||||
}
|
||||
|
@ -293,7 +312,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
if (this.partyUiMode !== PartyUiMode.SPLICE) {
|
||||
this.clearOptions();
|
||||
}
|
||||
if (this.selectCallback) {
|
||||
if (this.selectCallback && this.partyUiMode !== PartyUiMode.CHECK) {
|
||||
if (option === PartyOption.TRANSFER) {
|
||||
if (this.transferCursor !== this.cursor) {
|
||||
(this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.transferQuantities[this.transferOptionCursor], this.cursor);
|
||||
|
@ -315,11 +334,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
selectCallback(this.cursor, option);
|
||||
}
|
||||
} else {
|
||||
if (option >= PartyOption.FORM_CHANGE_ITEM && this.scene.getCurrentPhase() instanceof CommandPhase) {
|
||||
switch (this.partyUiMode) {
|
||||
case PartyUiMode.SWITCH:
|
||||
case PartyUiMode.FAINT_SWITCH:
|
||||
case PartyUiMode.POST_BATTLE_SWITCH:
|
||||
if (option >= PartyOption.FORM_CHANGE_ITEM && this.scene.getCurrentPhase() instanceof SelectModifierPhase) {
|
||||
if (this.partyUiMode === PartyUiMode.CHECK) {
|
||||
let formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[];
|
||||
if (formChangeItemModifiers.find(m => m.active)) {
|
||||
formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active);
|
||||
|
@ -327,7 +343,6 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM];
|
||||
modifier.active = !modifier.active;
|
||||
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeItemTrigger, false, true);
|
||||
break;
|
||||
}
|
||||
} else if (this.cursor) {
|
||||
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor, option === PartyOption.PASS_BATON);
|
||||
|
@ -690,15 +705,6 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
this.options.push(PartyOption.PASS_BATON);
|
||||
}
|
||||
}
|
||||
if (this.scene.getCurrentPhase() instanceof CommandPhase) {
|
||||
formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[];
|
||||
if (formChangeItemModifiers.find(m => m.active)) {
|
||||
formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active);
|
||||
}
|
||||
for (let i = 0; i < formChangeItemModifiers.length; i++) {
|
||||
this.options.push(PartyOption.FORM_CHANGE_ITEM + i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PartyUiMode.REVIVAL_BLESSING:
|
||||
this.options.push(PartyOption.REVIVE);
|
||||
|
@ -724,6 +730,17 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
case PartyUiMode.RELEASE:
|
||||
this.options.push(PartyOption.RELEASE);
|
||||
break;
|
||||
case PartyUiMode.CHECK:
|
||||
if (this.scene.getCurrentPhase() instanceof SelectModifierPhase) {
|
||||
formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[];
|
||||
if (formChangeItemModifiers.find(m => m.active)) {
|
||||
formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active);
|
||||
}
|
||||
for (let i = 0; i < formChangeItemModifiers.length; i++) {
|
||||
this.options.push(PartyOption.FORM_CHANGE_ITEM + i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
this.options.push(PartyOption.SUMMARY);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import BattleScene from "../battle-scene";
|
||||
import { gameModes } from "../game-mode";
|
||||
import { GameMode } from "../game-mode";
|
||||
import { SessionSaveData } from "../system/game-data";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
|
@ -266,7 +266,7 @@ class SessionSlot extends Phaser.GameObjects.Container {
|
|||
async setupWithData(data: SessionSaveData) {
|
||||
this.remove(this.loadingLabel, true);
|
||||
|
||||
const gameModeLabel = addTextObject(this.scene, 8, 5, `${gameModes[data.gameMode]?.getName() || "Unknown"} - Wave ${data.waveIndex}`, TextStyle.WINDOW);
|
||||
const gameModeLabel = addTextObject(this.scene, 8, 5, `${GameMode.getModeName(data.gameMode) || "Unknown"} - Wave ${data.waveIndex}`, TextStyle.WINDOW);
|
||||
this.add(gameModeLabel);
|
||||
|
||||
const timestampLabel = addTextObject(this.scene, 8, 19, new Date(data.timestamp).toLocaleString(), TextStyle.WINDOW);
|
||||
|
|
|
@ -18,8 +18,8 @@ import { LevelMoves, pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "../
|
|||
import PokemonSpecies, { allSpecies, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species";
|
||||
import { Type } from "../data/type";
|
||||
import { Button } from "../enums/buttons";
|
||||
import { GameModes, gameModes } from "../game-mode";
|
||||
import { TitlePhase } from "../phases";
|
||||
import { GameModes } from "../game-mode";
|
||||
import { SelectChallengePhase, TitlePhase } from "../phases";
|
||||
import { AbilityAttr, DexAttr, DexAttrProps, DexEntry, StarterFormMoveData, StarterMoveset } from "../system/game-data";
|
||||
import { Passive as PassiveAttr } from "#app/data/enums/passive";
|
||||
import { Tutorial, handleTutorial } from "../tutorial";
|
||||
|
@ -31,6 +31,7 @@ import { StatsContainer } from "./stats-container";
|
|||
import { TextStyle, addBBCodeTextObject, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import * as Challenge from "../data/challenge";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
|
||||
export type StarterSelectCallback = (starters: Starter[]) => void;
|
||||
|
@ -245,7 +246,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
private iconAnimHandler: PokemonIconAnimHandler;
|
||||
|
||||
private starterSelectCallback: StarterSelectCallback;
|
||||
private gameMode: GameModes;
|
||||
|
||||
protected blockInput: boolean = false;
|
||||
|
||||
|
@ -724,14 +724,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
|
||||
show(args: any[]): boolean {
|
||||
this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers
|
||||
if (args.length >= 2 && args[0] instanceof Function && typeof args[1] === "number") {
|
||||
if (args.length >= 1 && args[0] instanceof Function) {
|
||||
super.show(args);
|
||||
this.starterSelectCallback = args[0] as StarterSelectCallback;
|
||||
|
||||
this.starterSelectContainer.setVisible(true);
|
||||
|
||||
this.gameMode = args[1];
|
||||
|
||||
this.setGenMode(false);
|
||||
this.setCursor(0);
|
||||
this.setGenMode(true);
|
||||
|
@ -957,7 +955,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
} else {
|
||||
this.blockInput = true;
|
||||
this.scene.clearPhaseQueue();
|
||||
if (this.scene.gameMode.isChallenge) {
|
||||
this.scene.pushPhase(new SelectChallengePhase(this.scene));
|
||||
} else {
|
||||
this.scene.pushPhase(new TitlePhase(this.scene));
|
||||
}
|
||||
this.scene.getCurrentPhase().end();
|
||||
success = true;
|
||||
}
|
||||
|
@ -1029,7 +1031,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
}
|
||||
}
|
||||
const species = this.genSpecies[this.getGenCursorWithScroll()][this.cursor];
|
||||
if (!isDupe && this.tryUpdateValue(this.scene.gameData.getSpeciesStarterValue(species.speciesId))) {
|
||||
|
||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge);
|
||||
|
||||
if (!isDupe && isValidForChallenge.value && this.tryUpdateValue(this.scene.gameData.getSpeciesStarterValue(species.speciesId))) {
|
||||
const cursorObj = this.starterCursorObjs[this.starterCursors.length];
|
||||
cursorObj.setVisible(true);
|
||||
cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y);
|
||||
|
@ -1521,13 +1527,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
}
|
||||
|
||||
getValueLimit(): integer {
|
||||
switch (this.gameMode) {
|
||||
const valueLimit = new Utils.IntegerHolder(0);
|
||||
switch (this.scene.gameMode.modeId) {
|
||||
case GameModes.ENDLESS:
|
||||
case GameModes.SPLICED_ENDLESS:
|
||||
return 15;
|
||||
valueLimit.value = 15;
|
||||
default:
|
||||
return 10;
|
||||
valueLimit.value = 10;
|
||||
}
|
||||
|
||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_POINTS, valueLimit);
|
||||
|
||||
return valueLimit.value;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
|
@ -2160,20 +2171,25 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
const speciesSprite = this.starterSelectGenIconContainers[g].getAt(s) as Phaser.GameObjects.Sprite;
|
||||
|
||||
/**
|
||||
* If remainValue greater than or equal pokemon species, the user can select.
|
||||
* If remainValue greater than or equal pokemon species and the pokemon is legal for this challenge, the user can select.
|
||||
* so that the alpha value of pokemon sprite set 1.
|
||||
*
|
||||
* If speciesStarterDexEntry?.caughtAttr is true, this species registered in stater.
|
||||
* we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too.
|
||||
*/
|
||||
if (remainValue >= speciesStarterValue) {
|
||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.genSpecies[g][s], isValidForChallenge);
|
||||
|
||||
const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value;
|
||||
|
||||
if (canBeChosen) {
|
||||
speciesSprite.setAlpha(1);
|
||||
if (speciesStarterDexEntry?.caughtAttr) {
|
||||
this.canAddParty = true;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* If remainValue less than pokemon, the use can't select.
|
||||
* If it can't be chosen, the user can't select.
|
||||
* so that the alpha value of pokemon sprite set 0.375.
|
||||
*/
|
||||
speciesSprite.setAlpha(0.375);
|
||||
|
@ -2202,8 +2218,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
|
||||
ui.showText(i18next.t("starterSelectUiHandler:confirmStartTeam"), null, () => {
|
||||
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||
const startRun = (gameMode: GameModes) => {
|
||||
this.scene.gameMode = gameModes[gameMode];
|
||||
const startRun = () => {
|
||||
this.scene.money = this.scene.gameMode.getStartingMoney();
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
const thisObj = this;
|
||||
|
@ -2222,7 +2237,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
};
|
||||
}));
|
||||
};
|
||||
startRun(this.gameMode);
|
||||
startRun();
|
||||
}, cancel, null, null, 19);
|
||||
});
|
||||
|
||||
|
|
|
@ -3,12 +3,19 @@ import { TextStyle, getTextColor } from "./text";
|
|||
import { Mode } from "./ui";
|
||||
import {Button} from "../enums/buttons";
|
||||
|
||||
/**
|
||||
* A basic abstract class to act as a holder and processor for UI elements.
|
||||
*/
|
||||
export default abstract class UiHandler {
|
||||
protected scene: BattleScene;
|
||||
protected mode: integer;
|
||||
protected cursor: integer = 0;
|
||||
public active: boolean = false;
|
||||
|
||||
/**
|
||||
* @param {BattleScene} scene The same scene as everything else.
|
||||
* @param {Mode} mode The mode of the UI element. These should be unique.
|
||||
*/
|
||||
constructor(scene: BattleScene, mode: Mode) {
|
||||
this.scene = scene;
|
||||
this.mode = mode;
|
||||
|
|
10
src/ui/ui.ts
10
src/ui/ui.ts
|
@ -14,6 +14,7 @@ import EvolutionSceneHandler from "./evolution-scene-handler";
|
|||
import TargetSelectUiHandler from "./target-select-ui-handler";
|
||||
import SettingsUiHandler from "./settings/settings-ui-handler";
|
||||
import SettingsGamepadUiHandler from "./settings/settings-gamepad-ui-handler";
|
||||
import GameChallengesUiHandler from "./challenges-select-ui-handler";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import AchvBar from "./achv-bar";
|
||||
import MenuUiHandler from "./menu-ui-handler";
|
||||
|
@ -80,7 +81,8 @@ export enum Mode {
|
|||
LOADING,
|
||||
SESSION_RELOAD,
|
||||
UNAVAILABLE,
|
||||
OUTDATED
|
||||
OUTDATED,
|
||||
CHALLENGE_SELECT
|
||||
}
|
||||
|
||||
const transitionModes = [
|
||||
|
@ -91,7 +93,8 @@ const transitionModes = [
|
|||
Mode.EVOLUTION_SCENE,
|
||||
Mode.EGG_HATCH_SCENE,
|
||||
Mode.EGG_LIST,
|
||||
Mode.EGG_GACHA
|
||||
Mode.EGG_GACHA,
|
||||
Mode.CHALLENGE_SELECT
|
||||
];
|
||||
|
||||
const noTransitionModes = [
|
||||
|
@ -173,7 +176,8 @@ export default class UI extends Phaser.GameObjects.Container {
|
|||
new LoadingModalUiHandler(scene),
|
||||
new SessionReloadModalUiHandler(scene),
|
||||
new UnavailableModalUiHandler(scene),
|
||||
new OutdatedModalUiHandler(scene)
|
||||
new OutdatedModalUiHandler(scene),
|
||||
new GameChallengesUiHandler(scene)
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue