Add fade back to starter select on game over

pull/1/head
Flashfyre 2023-04-21 22:59:09 -04:00
parent b50976d784
commit db31f961ad
7 changed files with 154 additions and 80 deletions

View File

@ -188,7 +188,7 @@ export class SelectBiomePhase extends BattlePhase {
start() { start() {
super.start(); super.start();
this.scene.arena.fadeOutBgm(2000); this.scene.arena.fadeOutBgm(2000, true);
const currentBiome = this.scene.arena.biomeType; const currentBiome = this.scene.arena.biomeType;
@ -1147,8 +1147,8 @@ export class WeatherEffectPhase extends CommonAnimPhase {
const playerPokemon = this.scene.getPlayerPokemon(); const playerPokemon = this.scene.getPlayerPokemon();
const enemyPokemon = this.scene.getEnemyPokemon(); const enemyPokemon = this.scene.getEnemyPokemon();
const playerImmune = !!playerPokemon.getTypes().filter(t => this.weather.isTypeDamageImmune(t)).length; const playerImmune = !playerPokemon || !!playerPokemon.getTypes().filter(t => this.weather.isTypeDamageImmune(t)).length;
const enemyImmune = !!enemyPokemon.getTypes().filter(t => this.weather.isTypeDamageImmune(t)).length; const enemyImmune = !enemyPokemon || !!enemyPokemon.getTypes().filter(t => this.weather.isTypeDamageImmune(t)).length;
if (!this.playerDelayed && !playerImmune) if (!this.playerDelayed && !playerImmune)
inflictDamage(playerPokemon); inflictDamage(playerPokemon);
@ -1291,9 +1291,9 @@ export class FaintPhase extends PokemonPhase {
this.scene.queueMessage(getPokemonMessage(this.getPokemon(), ' fainted!'), null, true); this.scene.queueMessage(getPokemonMessage(this.getPokemon(), ' fainted!'), null, true);
if (this.player) if (this.player) {
this.scene.unshiftPhase(new SwitchPhase(this.scene, true, false)); this.scene.unshiftPhase(this.scene.getParty().filter(p => p.hp).length ? new SwitchPhase(this.scene, true, false) : new GameOverPhase(this.scene));
else } else
this.scene.unshiftPhase(new VictoryPhase(this.scene)); this.scene.unshiftPhase(new VictoryPhase(this.scene));
const pokemon = this.getPokemon(); const pokemon = this.getPokemon();
@ -1396,6 +1396,27 @@ export class VictoryPhase extends PokemonPhase {
} }
} }
export class GameOverPhase extends BattlePhase {
constructor(scene: BattleScene) {
super(scene);
}
start() {
super.start();
this.scene.time.delayedCall(1000, () => {
this.scene.fadeOutBgm(5000, true);
this.scene.ui.fadeOut(5000).then(() => {
this.scene.clearPhaseQueue();
this.scene.ui.clearText();
this.scene.reset();
this.scene.newBattle();
this.end();
});
});
}
}
export class SwitchPhase extends BattlePhase { export class SwitchPhase extends BattlePhase {
private isModal: boolean; private isModal: boolean;
private doReturn: boolean; private doReturn: boolean;

View File

@ -37,12 +37,15 @@ export enum Button {
CYCLE_FORM, CYCLE_FORM,
CYCLE_GENDER, CYCLE_GENDER,
QUICK_START, QUICK_START,
RANDOM,
AUTO, AUTO,
SPEED_UP, SPEED_UP,
SLOW_DOWN SLOW_DOWN
} }
interface PokeballCounts {
[pb: string]: integer;
}
export default class BattleScene extends Phaser.Scene { export default class BattleScene extends Phaser.Scene {
public auto: boolean; public auto: boolean;
public gameSpeed: integer = 1; public gameSpeed: integer = 1;
@ -65,7 +68,7 @@ export default class BattleScene extends Phaser.Scene {
public arena: Arena; public arena: Arena;
public trainer: Phaser.GameObjects.Sprite; public trainer: Phaser.GameObjects.Sprite;
public currentBattle: Battle; public currentBattle: Battle;
public pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ])); public pokeballCounts: PokeballCounts;
private party: PlayerPokemon[]; private party: PlayerPokemon[];
private waveCountText: Phaser.GameObjects.Text; private waveCountText: Phaser.GameObjects.Text;
private modifierBar: ModifierBar; private modifierBar: ModifierBar;
@ -302,7 +305,7 @@ export default class BattleScene extends Phaser.Scene {
this.add.existing(this.enemyModifierBar); this.add.existing(this.enemyModifierBar);
uiContainer.add(this.enemyModifierBar); uiContainer.add(this.enemyModifierBar);
this.waveCountText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, '1', TextStyle.BATTLE_INFO); this.waveCountText = addTextObject(this, (this.game.canvas.width / 6) - 2, 0, startingWave.toString(), TextStyle.BATTLE_INFO);
this.waveCountText.setOrigin(1, 0); this.waveCountText.setOrigin(1, 0);
this.updateWaveCountPosition(); this.updateWaveCountPosition();
this.fieldUI.add(this.waveCountText); this.fieldUI.add(this.waveCountText);
@ -311,22 +314,14 @@ export default class BattleScene extends Phaser.Scene {
let loadPokemonAssets = []; let loadPokemonAssets = [];
const isRandom = this.isButtonPressed(Button.RANDOM); // For testing purposes this.quickStart = this.quickStart || this.isButtonPressed(Button.QUICK_START);
this.quickStart = this.quickStart || isRandom || this.isButtonPressed(Button.QUICK_START);
if (isRandom) { this.arenaBg = this.add.sprite(0, 0, 'plains_bg');
const biomes = Utils.getEnumValues(Biome); this.arenaBgTransition = this.add.sprite(0, 0, `plains_bg`);
this.newArena(biomes[Utils.randInt(biomes.length)]); this.arenaPlayer = this.add.sprite(0, 0, `plains_a`);
} else this.arenaPlayerTransition = this.add.sprite(0, 0, `plains_a`);
this.newArena(startingBiome); this.arenaEnemy = this.add.sprite(0, 0, `plains_b`);
this.arenaNextEnemy = this.add.sprite(0, 0, `plains_b`);
const biomeKey = this.arena.getBiomeKey();
this.arenaBg = this.add.sprite(0, 0, `${biomeKey}_bg`);
this.arenaBgTransition = this.add.sprite(0, 0, `${biomeKey}_bg`);
this.arenaPlayer = this.add.sprite(340, 20, `${biomeKey}_a`);
this.arenaPlayerTransition = this.add.sprite(40, 20, `${biomeKey}_a`);
this.arenaEnemy = this.add.sprite(-240, 13, `${biomeKey}_b`);
this.arenaNextEnemy = this.add.sprite(-240, 13, `${biomeKey}_b`);
this.arenaBgTransition.setVisible(false); this.arenaBgTransition.setVisible(false);
this.arenaPlayerTransition.setVisible(false); this.arenaPlayerTransition.setVisible(false);
@ -338,9 +333,7 @@ export default class BattleScene extends Phaser.Scene {
if (this.quickStart) { if (this.quickStart) {
for (let s = 0; s < 3; s++) { for (let s = 0; s < 3; s++) {
const playerSpecies = (!isRandom const playerSpecies = getPokemonSpecies((getPokemonSpecies(s === 0 ? Species.TORCHIC : s === 1 ? Species.TREECKO : Species.MUDKIP)).getSpeciesForLevel(startingLevel, true));
? getPokemonSpecies((getPokemonSpecies(s === 0 ? Species.TORCHIC : s === 1 ? Species.TREECKO : Species.MUDKIP)).getSpeciesForLevel(startingLevel, true))
: this.randomSpecies(startingWave, startingLevel));
const playerPokemon = new PlayerPokemon(this, playerSpecies, startingLevel, 0); const playerPokemon = new PlayerPokemon(this, playerSpecies, startingLevel, 0);
playerPokemon.setVisible(false); playerPokemon.setVisible(false);
loadPokemonAssets.push(playerPokemon.loadAssets()); loadPokemonAssets.push(playerPokemon.loadAssets());
@ -356,7 +349,7 @@ export default class BattleScene extends Phaser.Scene {
frameRate: 16 frameRate: 16
}); });
const trainer = this.add.sprite(406, 132, 'trainer_m'); const trainer = this.add.sprite(0, 0, 'trainer_m');
trainer.setOrigin(0.5, 1); trainer.setOrigin(0.5, 1);
field.add(trainer); field.add(trainer);
@ -371,6 +364,8 @@ export default class BattleScene extends Phaser.Scene {
showOnStart: true showOnStart: true
}); });
this.reset();
const ui = new UI(this); const ui = new UI(this);
this.uiContainer.add(ui); this.uiContainer.add(ui);
@ -407,7 +402,6 @@ export default class BattleScene extends Phaser.Scene {
[Button.CYCLE_FORM]: [keyCodes.F], [Button.CYCLE_FORM]: [keyCodes.F],
[Button.CYCLE_GENDER]: [keyCodes.G], [Button.CYCLE_GENDER]: [keyCodes.G],
[Button.QUICK_START]: [keyCodes.Q], [Button.QUICK_START]: [keyCodes.Q],
[Button.RANDOM]: [keyCodes.R],
[Button.AUTO]: [keyCodes.F2], [Button.AUTO]: [keyCodes.F2],
[Button.SPEED_UP]: [keyCodes.PLUS], [Button.SPEED_UP]: [keyCodes.PLUS],
[Button.SLOW_DOWN]: [keyCodes.MINUS] [Button.SLOW_DOWN]: [keyCodes.MINUS]
@ -436,7 +430,44 @@ export default class BattleScene extends Phaser.Scene {
} }
getEnemyPokemon(): EnemyPokemon { getEnemyPokemon(): EnemyPokemon {
return this.currentBattle.enemyPokemon; return this.currentBattle?.enemyPokemon;
}
reset(): void {
this.pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ]));
this.modifiers = [];
this.enemyModifiers = [];
this.modifierBar.removeAll(true);
this.enemyModifierBar.removeAll(true);
for (let p of this.getParty())
p.destroy();
this.party = [];
for (let p of this.getEnemyParty())
p.destroy();
this.currentBattle = null;
this.waveCountText.setText(startingWave.toString());
this.newArena(startingBiome);
const biomeKey = this.arena.getBiomeKey();
this.arenaBg.setTexture(`${biomeKey}_bg`);
this.arenaBgTransition.setTexture(`${biomeKey}_bg`);
this.arenaPlayer.setTexture(`${biomeKey}_a`);
this.arenaPlayerTransition.setTexture(`${biomeKey}_a`);
this.arenaEnemy.setTexture(`${biomeKey}_b`);
this.arenaNextEnemy.setTexture(`${biomeKey}_b`);
this.arenaBgTransition.setPosition(0, 0);
this.arenaPlayer.setPosition(340, 20);
this.arenaPlayerTransition.setPosition(40, 2);
this.arenaEnemy.setPosition(-240, 13);
this.arenaNextEnemy.setPosition(-240, 13);
this.trainer.setTexture('trainer_m');
this.trainer.setPosition(406, 132);
} }
newBattle(): Battle { newBattle(): Battle {
@ -565,8 +596,8 @@ export default class BattleScene extends Phaser.Scene {
this.bgm.resume(); this.bgm.resume();
} }
fadeOutBgm(destroy?: boolean): void { fadeOutBgm(duration?: integer, destroy?: boolean): void {
this.arena.fadeOutBgm(500, destroy); this.arena.fadeOutBgm(duration || 500, destroy);
} }
playSoundWithoutBgm(soundName: string, pauseDuration?: integer): void { playSoundWithoutBgm(soundName: string, pauseDuration?: integer): void {

View File

@ -40,7 +40,7 @@ export class EvolutionPhase extends BattlePhase {
return; return;
} }
this.scene.fadeOutBgm(false); this.scene.fadeOutBgm(null, false);
this.evolutionContainer = (this.scene.ui.getHandler() as EvolutionSceneHandler).evolutionContainer; this.evolutionContainer = (this.scene.ui.getHandler() as EvolutionSceneHandler).evolutionContainer;

View File

@ -539,60 +539,60 @@ const modifierPool = {
new WeightedModifierType(modifierTypes.POKEBALL, 6), new WeightedModifierType(modifierTypes.POKEBALL, 6),
new WeightedModifierType(modifierTypes.RARE_CANDY, 2), new WeightedModifierType(modifierTypes.RARE_CANDY, 2),
new WeightedModifierType(modifierTypes.POTION, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.POTION, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 10 || p.getHpRatio() <= 0.875).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 10 || p.getHpRatio() <= 0.875).length, 3);
return thresholdPartyMemberCount * 3; return thresholdPartyMemberCount * 3;
}), }),
new WeightedModifierType(modifierTypes.SUPER_POTION, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.SUPER_POTION, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 25 || p.getHpRatio() <= 0.75).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 25 || p.getHpRatio() <= 0.75).length, 3);
return thresholdPartyMemberCount; return thresholdPartyMemberCount;
}), }),
new WeightedModifierType(modifierTypes.ETHER, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.ETHER, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
return thresholdPartyMemberCount * 3; return thresholdPartyMemberCount * 3;
}), }),
new WeightedModifierType(modifierTypes.MAX_ETHER, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.MAX_ETHER, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
return thresholdPartyMemberCount; return thresholdPartyMemberCount;
}), }),
new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4), new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4),
new WeightedModifierType(modifierTypes.BERRY, 2) new WeightedModifierType(modifierTypes.BERRY, 2)
].map(m => { m.setTier(ModifierTier.COMMON); return m; }), ].map(m => { m.setTier(ModifierTier.COMMON); return m; }),
[ModifierTier.GREAT]: [ [ModifierTier.GREAT]: [
new WeightedModifierType(modifierTypes.GREAT_BALL, 12), new WeightedModifierType(modifierTypes.GREAT_BALL, 6),
new WeightedModifierType(modifierTypes.FULL_HEAL, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.FULL_HEAL, (party: Pokemon[]) => {
const statusEffectPartyMemberCount = party.filter(p => p.hp && !!p.status).length; const statusEffectPartyMemberCount = Math.min(party.filter(p => p.hp && !!p.status).length, 3);
return statusEffectPartyMemberCount * 8; return statusEffectPartyMemberCount * 6;
}), }),
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
const faintedPartyMemberCount = party.filter(p => !p.hp).length; const faintedPartyMemberCount = Math.min(party.filter(p => !p.hp).length, 3);
return faintedPartyMemberCount * 6; return faintedPartyMemberCount * 9;
}), }),
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
const faintedPartyMemberCount = party.filter(p => !p.hp).length; const faintedPartyMemberCount = Math.min(party.filter(p => !p.hp).length, 3);
return faintedPartyMemberCount * 2; return faintedPartyMemberCount * 3;
}), }),
new WeightedModifierType(modifierTypes.SACRED_ASH, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.SACRED_ASH, (party: Pokemon[]) => {
return party.filter(p => !p.hp).length >= Math.ceil(party.length / 2) ? 1 : 0; return party.filter(p => !p.hp).length >= Math.ceil(party.length / 2) ? 1 : 0;
}), }),
new WeightedModifierType(modifierTypes.HYPER_POTION, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.HYPER_POTION, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length, 3);
return thresholdPartyMemberCount * 2; return thresholdPartyMemberCount * 3;
}), }),
new WeightedModifierType(modifierTypes.MAX_POTION, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.MAX_POTION, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length, 3);
return Math.ceil(thresholdPartyMemberCount / 1.5); return thresholdPartyMemberCount;
}), }),
new WeightedModifierType(modifierTypes.ELIXIR, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.ELIXIR, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
return thresholdPartyMemberCount * 2; return thresholdPartyMemberCount * 3;
}), }),
new WeightedModifierType(modifierTypes.MAX_ELIXIR, (party: Pokemon[]) => { new WeightedModifierType(modifierTypes.MAX_ELIXIR, (party: Pokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length; const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
return Math.ceil(thresholdPartyMemberCount / 1.5); return thresholdPartyMemberCount;
}), }),
new WeightedModifierType(modifierTypes.TM, 4), new WeightedModifierType(modifierTypes.TM, 2),
new WeightedModifierType(modifierTypes.EXP_SHARE, 2), modifierTypes.EXP_SHARE,
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 4) new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3)
].map(m => { m.setTier(ModifierTier.GREAT); return m; }), ].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
[ModifierTier.ULTRA]: [ [ModifierTier.ULTRA]: [
new WeightedModifierType(modifierTypes.ULTRA_BALL, 8), new WeightedModifierType(modifierTypes.ULTRA_BALL, 8),

View File

@ -78,7 +78,7 @@ export abstract class PersistentModifier extends Modifier {
add(modifiers: PersistentModifier[], virtual: boolean): boolean { add(modifiers: PersistentModifier[], virtual: boolean): boolean {
for (let modifier of modifiers) { for (let modifier of modifiers) {
if (this.match(modifier)) if (this.match(modifier))
return modifier.incrementStack(modifier.stackCount, virtual); return modifier.incrementStack(this.stackCount, virtual);
} }
if (virtual) { if (virtual) {

View File

@ -536,5 +536,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
super.clear(); super.clear();
this.cursor = -1; this.cursor = -1;
this.starterSelectContainer.setVisible(false); this.starterSelectContainer.setVisible(false);
while (this.starterCursors.length)
this.popStarter();
} }
} }

View File

@ -43,7 +43,7 @@ export default class UI extends Phaser.GameObjects.Container {
private handlers: UiHandler[]; private handlers: UiHandler[];
private overlay: Phaser.GameObjects.Rectangle; private overlay: Phaser.GameObjects.Rectangle;
private transitioning: boolean; private overlayActive: boolean;
constructor(scene: BattleScene) { constructor(scene: BattleScene) {
super(scene, 0, scene.game.canvas.height / 6); super(scene, 0, scene.game.canvas.height / 6);
@ -83,7 +83,7 @@ export default class UI extends Phaser.GameObjects.Container {
} }
processInput(button: Button): void { processInput(button: Button): void {
if (this.transitioning) if (this.overlayActive)
return; return;
this.getHandler().processInput(button); this.getHandler().processInput(button);
@ -121,6 +121,41 @@ export default class UI extends Phaser.GameObjects.Container {
this.scene.sound.play('error'); this.scene.sound.play('error');
} }
fadeOut(duration: integer): Promise<void> {
return new Promise(resolve => {
if (this.overlayActive) {
resolve();
return;
}
this.overlayActive = true;
this.overlay.setAlpha(0);
this.overlay.setVisible(true);
this.scene.tweens.add({
targets: this.overlay,
alpha: 1,
duration: duration,
ease: 'Sine.easeOut',
onComplete: () => resolve()
});
});
}
fadeIn(duration: integer): Promise<void> {
return new Promise(resolve => {
this.scene.tweens.add({
targets: this.overlay,
alpha: 0,
duration: duration,
ease: 'Sine.easeIn',
onComplete: () => {
this.overlay.setVisible(false);
resolve();
}
});
this.overlayActive = false;
});
}
private setModeInternal(mode: Mode, clear: boolean, forceTransition: boolean, args: any[]): Promise<void> { private setModeInternal(mode: Mode, clear: boolean, forceTransition: boolean, args: any[]): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
if (this.mode === mode && !forceTransition) { if (this.mode === mode && !forceTransition) {
@ -138,28 +173,12 @@ export default class UI extends Phaser.GameObjects.Container {
}; };
if ((transitionModes.indexOf(this.mode) > -1 || transitionModes.indexOf(mode) > -1) if ((transitionModes.indexOf(this.mode) > -1 || transitionModes.indexOf(mode) > -1)
&& (noTransitionModes.indexOf(this.mode) === -1 && noTransitionModes.indexOf(mode) === -1) && !(this.scene as BattleScene).auto) { && (noTransitionModes.indexOf(this.mode) === -1 && noTransitionModes.indexOf(mode) === -1) && !(this.scene as BattleScene).auto) {
this.transitioning = true; this.fadeOut(250).then(() => {
this.overlay.setAlpha(0);
this.overlay.setVisible(true);
this.scene.tweens.add({
targets: this.overlay,
alpha: 1,
duration: 250,
ease: 'Sine.easeOut',
onComplete: () => {
this.scene.time.delayedCall(100, () => { this.scene.time.delayedCall(100, () => {
doSetMode(); doSetMode();
this.scene.tweens.add({ this.fadeIn(250);
targets: this.overlay,
alpha: 0,
duration: 250,
ease: 'Sine.easeIn',
onComplete: () => this.overlay.setVisible(false)
});
this.transitioning = false;
});
}
}); });
})
} else } else
doSetMode(); doSetMode();
}); });