Add endless mode

Add endless mode; prevent stat booster items from being transferred or stolen
This commit is contained in:
Flashfyre 2023-05-31 19:54:57 -04:00
parent ac9814e665
commit 9faa489f19
16 changed files with 241 additions and 112 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

View File

@ -10,6 +10,7 @@ import { CommonAnim } from "./data/battle-anims";
import { Type } from "./data/type"; import { Type } from "./data/type";
import Move, { Moves } from "./data/move"; import Move, { Moves } from "./data/move";
import { ArenaTag, ArenaTagType, getArenaTag } from "./data/arena-tag"; import { ArenaTag, ArenaTagType, getArenaTag } from "./data/arena-tag";
import { GameMode } from "./game-mode";
export class Arena { export class Arena {
public scene: BattleScene; public scene: BattleScene;
@ -29,7 +30,8 @@ export class Arena {
} }
randomSpecies(waveIndex: integer, level: integer, attempt?: integer): PokemonSpecies { randomSpecies(waveIndex: integer, level: integer, attempt?: integer): PokemonSpecies {
const isBoss = waveIndex % 10 === 0 && !!this.pokemonPool[BiomePoolTier.BOSS].length; const isBoss = waveIndex % 10 === 0 && !!this.pokemonPool[BiomePoolTier.BOSS].length
&& (this.biomeType !== Biome.END || this.scene.gameMode !== GameMode.ENDLESS || waveIndex % 250 === 0);
const tierValue = Utils.randInt(!isBoss ? 512 : 64); const tierValue = Utils.randInt(!isBoss ? 512 : 64);
let tier = !isBoss let tier = !isBoss
? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE ? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE

View File

@ -29,6 +29,7 @@ import { CheckTrappedAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr,
import { Unlockables, getUnlockableName } from "./system/unlockables"; import { Unlockables, getUnlockableName } from "./system/unlockables";
import { getBiomeKey } from "./arena"; import { getBiomeKey } from "./arena";
import { BattlerIndex, TurnCommand } from "./battle"; import { BattlerIndex, TurnCommand } from "./battle";
import { GameMode } from "./game-mode";
export class CheckLoadPhase extends BattlePhase { export class CheckLoadPhase extends BattlePhase {
private loaded: boolean; private loaded: boolean;
@ -369,9 +370,16 @@ export class SelectBiomePhase extends BattlePhase {
this.end(); this.end();
}; };
if (this.scene.currentBattle.waveIndex === this.scene.finalWave - 9) if (this.scene.gameMode === GameMode.CLASSIC && this.scene.currentBattle.waveIndex === this.scene.finalWave - 9)
setNextBiome(Biome.END); setNextBiome(Biome.END);
else if (Array.isArray(biomeLinks[currentBiome])) { else if (this.scene.gameMode === GameMode.ENDLESS) {
if (this.scene.currentBattle.waveIndex % 50 === 0)
setNextBiome(Biome.END);
else {
const allBiomes = Utils.getEnumValues(Biome);
setNextBiome(allBiomes[Utils.randInt(allBiomes.length - 2, 1)]);
}
} else if (Array.isArray(biomeLinks[currentBiome])) {
const biomes = biomeLinks[currentBiome] as Biome[]; const biomes = biomeLinks[currentBiome] as Biome[];
if (this.scene.findModifier(m => m instanceof MapModifier)) { if (this.scene.findModifier(m => m instanceof MapModifier)) {
this.scene.ui.setMode(Mode.BIOME_SELECT, currentBiome, (biomeIndex: integer) => { this.scene.ui.setMode(Mode.BIOME_SELECT, currentBiome, (biomeIndex: integer) => {
@ -1841,7 +1849,7 @@ export class VictoryPhase extends PokemonPhase {
if (!this.scene.getEnemyField().filter(p => !p?.isFainted(true)).length) { if (!this.scene.getEnemyField().filter(p => !p?.isFainted(true)).length) {
this.scene.pushPhase(new BattleEndPhase(this.scene)); this.scene.pushPhase(new BattleEndPhase(this.scene));
if (this.scene.currentBattle.waveIndex < this.scene.finalWave) { if (this.scene.gameMode === GameMode.ENDLESS || this.scene.currentBattle.waveIndex < this.scene.finalWave) {
this.scene.pushPhase(new SelectModifierPhase(this.scene)); this.scene.pushPhase(new SelectModifierPhase(this.scene));
this.scene.pushPhase(new NewBattlePhase(this.scene)); this.scene.pushPhase(new NewBattlePhase(this.scene));
} else } else
@ -1880,6 +1888,8 @@ export class GameOverPhase extends BattlePhase {
} }
end(): void { end(): void {
if (!this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE])
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.ENDLESS_MODE));
if (!this.scene.gameData.unlocks[Unlockables.MINI_BLACK_HOLE]) if (!this.scene.gameData.unlocks[Unlockables.MINI_BLACK_HOLE])
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.MINI_BLACK_HOLE)); this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.MINI_BLACK_HOLE));
@ -2417,7 +2427,7 @@ export class SelectModifierPhase extends BattlePhase {
if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) {
this.scene.ui.setMode(Mode.MODIFIER_SELECT).then(() => { this.scene.ui.setMode(Mode.MODIFIER_SELECT).then(() => {
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[];
const itemModifier = itemModifiers[itemIndex]; const itemModifier = itemModifiers[itemIndex];
this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, true).then(success => { this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, true).then(success => {
if (success) { if (success) {

View File

@ -21,6 +21,7 @@ import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './m
import AbilityBar from './ui/ability-bar'; import AbilityBar from './ui/ability-bar';
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability';
import Battle from './battle'; import Battle from './battle';
import { GameMode } from './game-mode';
const enableAuto = true; const enableAuto = true;
const quickStart = false; const quickStart = false;
@ -73,6 +74,7 @@ export default class BattleScene extends Phaser.Scene {
public arenaEnemy: ArenaBase; public arenaEnemy: ArenaBase;
public arenaNextEnemy: ArenaBase; public arenaNextEnemy: ArenaBase;
public arena: Arena; public arena: Arena;
public gameMode: GameMode;
public trainer: Phaser.GameObjects.Sprite; public trainer: Phaser.GameObjects.Sprite;
public currentBattle: Battle; public currentBattle: Battle;
public pokeballCounts: PokeballCounts; public pokeballCounts: PokeballCounts;
@ -167,6 +169,7 @@ export default class BattleScene extends Phaser.Scene {
this.loadImage('ability_bar', 'ui'); this.loadImage('ability_bar', 'ui');
this.loadImage('ball_window', 'ui'); this.loadImage('ball_window', 'ui');
this.loadImage('boolean_window', 'ui'); this.loadImage('boolean_window', 'ui');
this.loadImage('game_mode_select_window', 'ui');
this.loadImage('party_bg', 'ui'); this.loadImage('party_bg', 'ui');
this.loadImage('party_bg_double', 'ui'); this.loadImage('party_bg_double', 'ui');
@ -530,7 +533,7 @@ export default class BattleScene extends Phaser.Scene {
if (!waveIndex) { if (!waveIndex) {
if (lastBattle) { if (lastBattle) {
this.getEnemyField().forEach(enemyPokemon => enemyPokemon.destroy()); this.getEnemyField().forEach(enemyPokemon => enemyPokemon.destroy());
if (lastBattle.waveIndex % 10) if (this.gameMode === GameMode.CLASSIC && lastBattle.waveIndex % 10)
this.pushPhase(new NextEncounterPhase(this)); this.pushPhase(new NextEncounterPhase(this));
else { else {
this.pushPhase(new SelectBiomePhase(this)); this.pushPhase(new SelectBiomePhase(this));

4
src/game-mode.ts Normal file
View File

@ -0,0 +1,4 @@
export enum GameMode {
CLASSIC,
ENDLESS
}

View File

@ -11,6 +11,7 @@ import * as Utils from '../utils';
import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from '../data/temp-battle-stat'; import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from '../data/temp-battle-stat';
import { BerryType, getBerryEffectDescription, getBerryName } from '../data/berry'; import { BerryType, getBerryEffectDescription, getBerryName } from '../data/berry';
import { Unlockables } from '../system/unlockables'; import { Unlockables } from '../system/unlockables';
import { GameMode } from '../game-mode';
type Modifier = Modifiers.Modifier; type Modifier = Modifiers.Modifier;
@ -694,7 +695,7 @@ const modifierPool = {
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3); const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
return thresholdPartyMemberCount; return thresholdPartyMemberCount;
}), }),
new WeightedModifierType(modifierTypes.MAP, 1), new WeightedModifierType(modifierTypes.MAP, (party: Pokemon[]) => party[0].scene.gameMode === GameMode.CLASSIC ? 1 : 0),
new WeightedModifierType(modifierTypes.TM_GREAT, 2), new WeightedModifierType(modifierTypes.TM_GREAT, 2),
new WeightedModifierType(modifierTypes.EXP_SHARE, 1), new WeightedModifierType(modifierTypes.EXP_SHARE, 1),
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3) new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3)
@ -745,8 +746,7 @@ const enemyModifierPool = {
new WeightedModifierType(modifierTypes.SHELL_BELL, 1), new WeightedModifierType(modifierTypes.SHELL_BELL, 1),
].map(m => { m.setTier(ModifierTier.ULTRA); return m; }), ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
[ModifierTier.MASTER]: [ [ModifierTier.MASTER]: [
new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1), new WeightedModifierType(modifierTypes.GOLDEN_EGG, 1)
new WeightedModifierType(modifierTypes.MINI_BLACK_HOLE, 1)
].map(m => { m.setTier(ModifierTier.MASTER); return m; }) ].map(m => { m.setTier(ModifierTier.MASTER); return m; })
}; };

View File

@ -283,6 +283,10 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
return super.shouldApply(args) && args.length && args[0] instanceof Pokemon && (this.pokemonId === -1 || (args[0] as Pokemon).id === this.pokemonId); return super.shouldApply(args) && args.length && args[0] instanceof Pokemon && (this.pokemonId === -1 || (args[0] as Pokemon).id === this.pokemonId);
} }
getTransferrable(withinParty: boolean) {
return true;
}
getIcon(scene: BattleScene, forSummary?: boolean): Phaser.GameObjects.Container { getIcon(scene: BattleScene, forSummary?: boolean): Phaser.GameObjects.Container {
const container = !forSummary ? scene.add.container(0, 0) : super.getIcon(scene); const container = !forSummary ? scene.add.container(0, 0) : super.getIcon(scene);
@ -357,6 +361,10 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
return true; return true;
} }
getTransferrable(_withinParty: boolean): boolean {
return false;
}
} }
export class AttackTypeBoosterModifier extends PokemonHeldItemModifier { export class AttackTypeBoosterModifier extends PokemonHeldItemModifier {
@ -1014,9 +1022,11 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
if (!transferredItemCount) if (!transferredItemCount)
return false; return false;
const withinParty = pokemon.isPlayer() === targetPokemon.isPlayer();
const transferredModifierTypes: ModifierTypes.ModifierType[] = []; const transferredModifierTypes: ModifierTypes.ModifierType[] = [];
const itemModifiers = pokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier const itemModifiers = pokemon.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).pokemonId === targetPokemon.id && !m.matchType(this), targetPokemon.isPlayer()) as PokemonHeldItemModifier[]; && (m as PokemonHeldItemModifier).pokemonId === targetPokemon.id && m.getTransferrable(withinParty), targetPokemon.isPlayer()) as PokemonHeldItemModifier[];
for (let i = 0; i < transferredItemCount; i++) { for (let i = 0; i < transferredItemCount; i++) {
if (!itemModifiers.length) if (!itemModifiers.length)
@ -1053,6 +1063,10 @@ export class TurnHeldItemTransferModifier extends HeldItemTransferModifier {
return new TurnHeldItemTransferModifier(this.type, this.pokemonId, this.stackCount); return new TurnHeldItemTransferModifier(this.type, this.pokemonId, this.stackCount);
} }
getTransferrable(withinParty: boolean) {
return withinParty;
}
getTransferredItemCount(): integer { getTransferredItemCount(): integer {
return this.getStackCount(); return this.getStackCount();
} }

View File

@ -10,6 +10,7 @@ import PersistentModifierData from "./modifier-data";
import { PokemonHeldItemModifier } from "../modifier/modifier"; import { PokemonHeldItemModifier } from "../modifier/modifier";
import ArenaData from "./arena-data"; import ArenaData from "./arena-data";
import { Unlockables } from "./unlockables"; import { Unlockables } from "./unlockables";
import { GameMode } from "../game-mode";
interface SystemSaveData { interface SystemSaveData {
trainerId: integer; trainerId: integer;
@ -20,6 +21,7 @@ interface SystemSaveData {
} }
interface SessionSaveData { interface SessionSaveData {
gameMode: GameMode;
party: PokemonData[]; party: PokemonData[];
enemyField: PokemonData[]; enemyField: PokemonData[];
modifiers: PersistentModifierData[]; modifiers: PersistentModifierData[];
@ -75,6 +77,7 @@ export class GameData {
this.trainerId = Utils.randInt(65536); this.trainerId = Utils.randInt(65536);
this.secretId = Utils.randInt(65536); this.secretId = Utils.randInt(65536);
this.unlocks = { this.unlocks = {
[Unlockables.ENDLESS_MODE]: false,
[Unlockables.MINI_BLACK_HOLE]: false [Unlockables.MINI_BLACK_HOLE]: false
}; };
this.initDexData(); this.initDexData();
@ -125,6 +128,7 @@ export class GameData {
saveSession(scene: BattleScene): boolean { saveSession(scene: BattleScene): boolean {
const sessionData = { const sessionData = {
gameMode: scene.gameMode,
party: scene.getParty().map(p => new PokemonData(p)), party: scene.getParty().map(p => new PokemonData(p)),
enemyField: scene.getEnemyField().map(p => new PokemonData(p)), enemyField: scene.getEnemyField().map(p => new PokemonData(p)),
modifiers: scene.findModifiers(() => true).map(m => new PersistentModifierData(m, true)), modifiers: scene.findModifiers(() => true).map(m => new PersistentModifierData(m, true)),
@ -176,6 +180,8 @@ export class GameData {
console.debug(sessionData); console.debug(sessionData);
scene.gameMode = sessionData.gameMode || GameMode.CLASSIC;
const loadPokemonAssets: Promise<void>[] = []; const loadPokemonAssets: Promise<void>[] = [];
const party = scene.getParty(); const party = scene.getParty();

View File

@ -1,9 +1,12 @@
export enum Unlockables { export enum Unlockables {
ENDLESS_MODE,
MINI_BLACK_HOLE MINI_BLACK_HOLE
} }
export function getUnlockableName(unlockable: Unlockables) { export function getUnlockableName(unlockable: Unlockables) {
switch (unlockable) { switch (unlockable) {
case Unlockables.ENDLESS_MODE:
return 'Endless Mode';
case Unlockables.MINI_BLACK_HOLE: case Unlockables.MINI_BLACK_HOLE:
return 'MINI BLACK HOLE'; return 'MINI BLACK HOLE';
} }

View File

@ -1,17 +1,9 @@
import BattleScene, { Button } from "../battle-scene"; import BattleScene, { Button } from "../battle-scene";
import OptionSelectUiHandler from "./option-select-ui-handler";
import { addTextObject, TextStyle } from "./text"; import { addTextObject, TextStyle } from "./text";
import { Mode } from "./ui"; import { Mode } from "./ui";
import UiHandler from "./uiHandler";
export default class ConfirmUiHandler extends UiHandler {
private yesHandler: Function;
private noHander: Function;
private confirmContainer: Phaser.GameObjects.Container;
private confirmBg: Phaser.GameObjects.Image;
private cursorObj: Phaser.GameObjects.Image;
export default class ConfirmUiHandler extends OptionSelectUiHandler {
private switchCheck: boolean; private switchCheck: boolean;
private switchCheckCursor: integer; private switchCheckCursor: integer;
@ -19,94 +11,34 @@ export default class ConfirmUiHandler extends UiHandler {
super(scene, Mode.CONFIRM); super(scene, Mode.CONFIRM);
} }
setup() { getWindowName(): string {
const ui = this.getUi(); return 'boolean_window';
}
this.confirmContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 49, -49); getWindowWidth(): integer {
this.confirmContainer.setVisible(false); return 48;
ui.add(this.confirmContainer); }
this.confirmBg = this.scene.add.image(0, 0, 'boolean_window'); getOptions(): string[] {
this.confirmBg.setOrigin(0, 1); return [ 'Yes', 'No' ];
this.confirmContainer.add(this.confirmBg);
const confirmText = addTextObject(this.scene, 0, 0, 'Yes\nNo', TextStyle.WINDOW, { maxLines: 2 });
confirmText.setPositionRelative(this.confirmBg, 16, 9);
confirmText.setLineSpacing(12);
this.confirmContainer.add(confirmText);
this.setCursor(0);
} }
show(args: any[]) { show(args: any[]) {
if (args.length >= 2 && args[0] instanceof Function && args[1] instanceof Function) { if (args.length >= 2 && args[0] instanceof Function && args[1] instanceof Function) {
super.show(args); super.show(args);
this.yesHandler = args[0] as Function;
this.noHander = args[1] as Function;
this.switchCheck = args.length >= 3 && args[2] as boolean; this.switchCheck = args.length >= 3 && args[2] as boolean;
this.confirmContainer.setVisible(true);
this.setCursor(this.switchCheck ? this.switchCheckCursor : 0); this.setCursor(this.switchCheck ? this.switchCheckCursor : 0);
} }
} }
processInput(button: Button) {
const ui = this.getUi();
let success = false;
if (button === Button.ACTION || button === Button.CANCEL) {
success = true;
if (button === Button.CANCEL)
this.setCursor(1);
const handler = this.cursor ? this.noHander : this.yesHandler;
handler();
this.clear();
} else {
switch (button) {
case Button.UP:
if (this.cursor)
success = this.setCursor(0);
break;
case Button.DOWN:
if (!this.cursor)
success = this.setCursor(1);
break;
}
}
if (success)
ui.playSelect();
}
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {
const ret = super.setCursor(cursor); const ret = super.setCursor(cursor);
if (ret && this.switchCheck) if (ret && this.switchCheck)
this.switchCheckCursor = this.cursor; this.switchCheckCursor = this.cursor;
if (!this.cursorObj) {
this.cursorObj = this.scene.add.image(0, 0, 'cursor');
this.confirmContainer.add(this.cursorObj);
}
this.cursorObj.setPositionRelative(this.confirmBg, 12, this.cursor ? 33 : 17);
return ret; return ret;
} }
clear() {
super.clear();
this.yesHandler = null;
this.noHander = null;
this.confirmContainer.setVisible(false);
this.eraseCursor();
}
eraseCursor() {
if (this.cursorObj)
this.cursorObj.destroy();
this.cursorObj = null;
}
} }

View File

@ -0,0 +1,22 @@
import BattleScene from "../battle-scene";
import OptionSelectUiHandler from "./option-select-ui-handler";
import { Mode } from "./ui";
export default class GameModeSelectUiHandler extends OptionSelectUiHandler {
constructor(scene: BattleScene) {
super(scene, Mode.GAME_MODE_SELECT);
}
getWindowName(): string {
return 'game_mode_select_window';
}
getWindowWidth(): integer {
return 64;
}
getOptions(): string[] {
return [ 'Classic', 'Endless', 'Cancel' ];
}
}

View File

@ -61,7 +61,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
this.getUi().clearText(); this.getUi().clearText();
const partyHasHeldItem = !!this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier).length; const partyHasHeldItem = !!this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).getTransferrable(true)).length;
this.transferButtonContainer.setVisible(false); this.transferButtonContainer.setVisible(false);
this.transferButtonContainer.setAlpha(0); this.transferButtonContainer.setAlpha(0);

View File

@ -0,0 +1,115 @@
import BattleScene, { Button } from "../battle-scene";
import { TextStyle, addTextObject } from "./text";
import { Mode } from "./ui";
import UiHandler from "./uiHandler";
export default abstract class OptionSelectUiHandler extends UiHandler {
protected handlers: Function[];
protected optionSelectContainer: Phaser.GameObjects.Container;
protected optionSelectBg: Phaser.GameObjects.Image;
private cursorObj: Phaser.GameObjects.Image;
constructor(scene: BattleScene, mode?: Mode) {
super(scene, mode);
}
abstract getWindowName(): string;
abstract getWindowWidth(): integer;
abstract getOptions(): string[];
setup() {
const ui = this.getUi();
this.optionSelectContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - (this.getWindowWidth() + 1), -(this.getWindowWidth() + 1));
this.optionSelectContainer.setVisible(false);
ui.add(this.optionSelectContainer);
this.optionSelectBg = this.scene.add.image(0, 0, this.getWindowName());
this.optionSelectBg.setOrigin(0, 1);
this.optionSelectContainer.add(this.optionSelectBg);
const options = this.getOptions();
const optionSelectText = addTextObject(this.scene, 0, 0, options.join('\n'), TextStyle.WINDOW, { maxLines: options.length });
optionSelectText.setPositionRelative(this.optionSelectBg, 16, 9);
optionSelectText.setLineSpacing(12);
this.optionSelectContainer.add(optionSelectText);
this.setCursor(0);
}
show(args: any[]) {
const options = this.getOptions();
if (args.length >= options.length && args[0] instanceof Function && args[1] instanceof Function) {
super.show(args);
this.handlers = args.slice(0, options.length) as Function[];
this.optionSelectContainer.setVisible(true);
this.setCursor(0);
}
}
processInput(button: Button) {
const ui = this.getUi();
let success = false;
const options = this.getOptions();
if (button === Button.ACTION || button === Button.CANCEL) {
success = true;
if (button === Button.CANCEL)
this.setCursor(options.length - 1);
const handler = this.handlers[this.cursor];
handler();
this.clear();
} else {
switch (button) {
case Button.UP:
if (this.cursor)
success = this.setCursor(this.cursor - 1);
break;
case Button.DOWN:
if (this.cursor < options.length - 1)
success = this.setCursor(this.cursor + 1);
break;
}
}
if (success)
ui.playSelect();
}
setCursor(cursor: integer): boolean {
const ret = super.setCursor(cursor);
if (!this.cursorObj) {
this.cursorObj = this.scene.add.image(0, 0, 'cursor');
this.optionSelectContainer.add(this.cursorObj);
}
this.cursorObj.setPositionRelative(this.optionSelectBg, 12, 17 + this.cursor * 16);
return ret;
}
clear() {
super.clear();
for (let h = 0; h < this.handlers.length; h++)
this.handlers[h] = null;
this.optionSelectContainer.setVisible(false);
this.eraseCursor();
}
eraseCursor() {
if (this.cursorObj)
this.cursorObj.destroy();
this.cursorObj = null;
}
}

View File

@ -200,7 +200,7 @@ export default class PartyUiHandler extends MessageUiHandler {
filterResult = this.moveSelectFilter(pokemon.moveset[this.optionsCursor]); filterResult = this.moveSelectFilter(pokemon.moveset[this.optionsCursor]);
} else { } else {
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).pokemonId === pokemon.id) as PokemonHeldItemModifier[]; && (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === pokemon.id) as PokemonHeldItemModifier[];
filterResult = (this.selectFilter as PokemonModifierTransferSelectFilter)(pokemon, itemModifiers[this.transferOptionCursor]); filterResult = (this.selectFilter as PokemonModifierTransferSelectFilter)(pokemon, itemModifiers[this.transferOptionCursor]);
} }
if (filterResult === null) { if (filterResult === null) {
@ -409,7 +409,8 @@ export default class PartyUiHandler extends MessageUiHandler {
const pokemon = this.scene.getParty()[this.cursor]; const pokemon = this.scene.getParty()[this.cursor];
const itemModifiers = this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER const itemModifiers = this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER
? this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === pokemon.id) as PokemonHeldItemModifier[] ? this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === pokemon.id) as PokemonHeldItemModifier[]
: null; : null;
if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) { if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) {

View File

@ -9,6 +9,8 @@ import { DexEntryDetails, StarterDexUnlockTree } from "../system/game-data";
import { Gender, getGenderColor, getGenderSymbol } from "../data/gender"; import { Gender, getGenderColor, getGenderSymbol } from "../data/gender";
import { pokemonPrevolutions } from "../data/pokemon-evolutions"; import { pokemonPrevolutions } from "../data/pokemon-evolutions";
import { abilities } from "../data/ability"; import { abilities } from "../data/ability";
import { GameMode } from "../game-mode";
import { Unlockables } from "../system/unlockables";
export type StarterSelectCallback = (starters: Starter[]) => void; export type StarterSelectCallback = (starters: Starter[]) => void;
@ -269,8 +271,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (this.speciesLoaded.get(species.speciesId)) if (this.speciesLoaded.get(species.speciesId))
species.cry(this.scene); species.cry(this.scene);
if (this.starterCursors.length === 3) { if (this.starterCursors.length === 3) {
const cancel = () => {
ui.setMode(Mode.STARTER_SELECT);
this.popStarter();
this.clearText();
};
ui.showText('Begin with these POKéMON?', null, () => { ui.showText('Begin with these POKéMON?', null, () => {
ui.setModeWithoutClear(Mode.CONFIRM, () => { ui.setModeWithoutClear(Mode.CONFIRM, () => {
const startRun = (gameMode: GameMode) => {
this.scene.gameMode = gameMode;
ui.setMode(Mode.STARTER_SELECT); ui.setMode(Mode.STARTER_SELECT);
const thisObj = this; const thisObj = this;
const originalStarterSelectCallback = this.starterSelectCallback; const originalStarterSelectCallback = this.starterSelectCallback;
@ -284,11 +293,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
abilityIndex: thisObj.starterDetails[i][3] abilityIndex: thisObj.starterDetails[i][3]
}; };
})); }));
}, () => { };
if (this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]) {
ui.setMode(Mode.STARTER_SELECT); ui.setMode(Mode.STARTER_SELECT);
this.popStarter(); ui.showText('Select a game mode.', null, () => {
this.clearText(); ui.setModeWithoutClear(Mode.GAME_MODE_SELECT, () => startRun(GameMode.CLASSIC), () => startRun(GameMode.ENDLESS), cancel);
}); });
} else
startRun(GameMode.CLASSIC);
}, cancel);
}); });
} }
success = true; success = true;

View File

@ -13,6 +13,7 @@ import StarterSelectUiHandler from './starter-select-ui-handler';
import EvolutionSceneHandler from './evolution-scene-handler'; import EvolutionSceneHandler from './evolution-scene-handler';
import BiomeSelectUiHandler from './biome-select-ui-handler'; import BiomeSelectUiHandler from './biome-select-ui-handler';
import TargetSelectUiHandler from './target-select-ui-handler'; import TargetSelectUiHandler from './target-select-ui-handler';
import GameModeSelectUiHandler from './game-mode-select-ui-handler';
export enum Mode { export enum Mode {
MESSAGE, MESSAGE,
@ -26,7 +27,8 @@ export enum Mode {
BIOME_SELECT, BIOME_SELECT,
STARTER_SELECT, STARTER_SELECT,
EVOLUTION_SCENE, EVOLUTION_SCENE,
CONFIRM CONFIRM,
GAME_MODE_SELECT
}; };
const transitionModes = [ const transitionModes = [
@ -37,7 +39,8 @@ const transitionModes = [
]; ];
const noTransitionModes = [ const noTransitionModes = [
Mode.CONFIRM Mode.CONFIRM,
Mode.GAME_MODE_SELECT
]; ];
export default class UI extends Phaser.GameObjects.Container { export default class UI extends Phaser.GameObjects.Container {
@ -63,7 +66,8 @@ export default class UI extends Phaser.GameObjects.Container {
new BiomeSelectUiHandler(scene), new BiomeSelectUiHandler(scene),
new StarterSelectUiHandler(scene), new StarterSelectUiHandler(scene),
new EvolutionSceneHandler(scene), new EvolutionSceneHandler(scene),
new ConfirmUiHandler(scene) new ConfirmUiHandler(scene),
new GameModeSelectUiHandler(scene)
]; ];
} }