Compare commits
4 Commits
main
...
nuzlocke-m
Author | SHA1 | Date |
---|---|---|
Flashfyre | 6a1da862d4 | |
Flashfyre | 62224aa3c9 | |
Flashfyre | cd1684180f | |
Flashfyre | ef6c354132 |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
|
@ -20,7 +20,6 @@ import { initMoves } from './data/move';
|
||||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from './modifier/modifier-type';
|
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from './modifier/modifier-type';
|
||||||
import AbilityBar from './ui/ability-bar';
|
import AbilityBar from './ui/ability-bar';
|
||||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
||||||
import { Abilities } from "./data/enums/abilities";
|
|
||||||
import { allAbilities } from "./data/ability";
|
import { allAbilities } from "./data/ability";
|
||||||
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
|
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
|
||||||
import { GameMode, GameModes, gameModes } from './game-mode';
|
import { GameMode, GameModes, gameModes } from './game-mode';
|
||||||
|
@ -53,7 +52,7 @@ import PokemonSpriteSparkleHandler from './field/pokemon-sprite-sparkle-handler'
|
||||||
import CharSprite from './ui/char-sprite';
|
import CharSprite from './ui/char-sprite';
|
||||||
import DamageNumberHandler from './field/damage-number-handler';
|
import DamageNumberHandler from './field/damage-number-handler';
|
||||||
import PokemonInfoContainer from './ui/pokemon-info-container';
|
import PokemonInfoContainer from './ui/pokemon-info-container';
|
||||||
import { biomeDepths } from './data/biomes';
|
import { biomeDepths, getBiomeName } from './data/biomes';
|
||||||
import { UiTheme } from './enums/ui-theme';
|
import { UiTheme } from './enums/ui-theme';
|
||||||
import { SceneBase } from './scene-base';
|
import { SceneBase } from './scene-base';
|
||||||
import CandyBar from './ui/candy-bar';
|
import CandyBar from './ui/candy-bar';
|
||||||
|
@ -136,6 +135,9 @@ export default class BattleScene extends SceneBase {
|
||||||
public arena: Arena;
|
public arena: Arena;
|
||||||
public gameMode: GameMode;
|
public gameMode: GameMode;
|
||||||
public score: integer;
|
public score: integer;
|
||||||
|
public victoryCount: integer;
|
||||||
|
public faintCount: integer;
|
||||||
|
public reviveCount: integer;
|
||||||
public lockModifierTiers: boolean;
|
public lockModifierTiers: boolean;
|
||||||
public trainer: Phaser.GameObjects.Sprite;
|
public trainer: Phaser.GameObjects.Sprite;
|
||||||
public lastEnemyTrainer: Trainer;
|
public lastEnemyTrainer: Trainer;
|
||||||
|
@ -188,6 +190,7 @@ export default class BattleScene extends SceneBase {
|
||||||
this.phaseQueuePrepend = [];
|
this.phaseQueuePrepend = [];
|
||||||
this.phaseQueuePrependSpliceIndex = -1;
|
this.phaseQueuePrependSpliceIndex = -1;
|
||||||
this.nextCommandPhaseQueue = [];
|
this.nextCommandPhaseQueue = [];
|
||||||
|
this.updateGameInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPokemonAtlas(key: string, atlasPath: string, experimental?: boolean) {
|
loadPokemonAtlas(key: string, atlasPath: string, experimental?: boolean) {
|
||||||
|
@ -623,6 +626,7 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
if (postProcess)
|
if (postProcess)
|
||||||
postProcess(pokemon);
|
postProcess(pokemon);
|
||||||
|
pokemon.calculateStats();
|
||||||
pokemon.init();
|
pokemon.init();
|
||||||
return pokemon;
|
return pokemon;
|
||||||
}
|
}
|
||||||
|
@ -756,6 +760,8 @@ export default class BattleScene extends SceneBase {
|
||||||
this.trainer.setPosition(406, 186);
|
this.trainer.setPosition(406, 186);
|
||||||
this.trainer.setVisible(true);
|
this.trainer.setVisible(true);
|
||||||
|
|
||||||
|
this.updateGameInfo();
|
||||||
|
|
||||||
if (reloadI18n) {
|
if (reloadI18n) {
|
||||||
const localizable: Localizable[] = [
|
const localizable: Localizable[] = [
|
||||||
...allSpecies,
|
...allSpecies,
|
||||||
|
@ -800,7 +806,7 @@ export default class BattleScene extends SceneBase {
|
||||||
|
|
||||||
const playerField = this.getPlayerField();
|
const playerField = this.getPlayerField();
|
||||||
|
|
||||||
if (this.gameMode.hasFixedBattles && fixedBattles.hasOwnProperty(newWaveIndex) && trainerData === undefined) {
|
if (this.gameMode.hasFixedBattles && fixedBattles.hasOwnProperty(newWaveIndex) && fixedBattles[newWaveIndex].condition(this) && trainerData === undefined) {
|
||||||
battleConfig = fixedBattles[newWaveIndex];
|
battleConfig = fixedBattles[newWaveIndex];
|
||||||
newDouble = battleConfig.double;
|
newDouble = battleConfig.double;
|
||||||
newBattleType = battleConfig.battleType;
|
newBattleType = battleConfig.battleType;
|
||||||
|
@ -811,14 +817,14 @@ export default class BattleScene extends SceneBase {
|
||||||
if (!this.gameMode.hasTrainers)
|
if (!this.gameMode.hasTrainers)
|
||||||
newBattleType = BattleType.WILD;
|
newBattleType = BattleType.WILD;
|
||||||
else if (battleType === undefined)
|
else if (battleType === undefined)
|
||||||
newBattleType = this.gameMode.isWaveTrainer(newWaveIndex, this.arena) ? BattleType.TRAINER : BattleType.WILD;
|
newBattleType = this.gameMode.isWaveTrainer(newWaveIndex, this) ? BattleType.TRAINER : BattleType.WILD;
|
||||||
else
|
else
|
||||||
newBattleType = battleType;
|
newBattleType = battleType;
|
||||||
|
|
||||||
if (newBattleType === BattleType.TRAINER) {
|
if (newBattleType === BattleType.TRAINER) {
|
||||||
const trainerType = this.arena.randomTrainerType(newWaveIndex);
|
const trainerType = this.arena.randomTrainerType(newWaveIndex);
|
||||||
let doubleTrainer = false;
|
let doubleTrainer = false;
|
||||||
if (trainerConfigs[trainerType].doubleOnly)
|
if (trainerConfigs[trainerType].doubleOnly && trainerConfigs[trainerType].hasGenders)
|
||||||
doubleTrainer = true;
|
doubleTrainer = true;
|
||||||
else if (trainerConfigs[trainerType].hasDouble) {
|
else if (trainerConfigs[trainerType].hasDouble) {
|
||||||
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8);
|
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8);
|
||||||
|
@ -879,7 +885,7 @@ export default class BattleScene extends SceneBase {
|
||||||
isNewBiome = !Utils.randSeedInt(6 - biomeWaves);
|
isNewBiome = !Utils.randSeedInt(6 - biomeWaves);
|
||||||
}, lastBattle.waveIndex << 4);
|
}, lastBattle.waveIndex << 4);
|
||||||
}
|
}
|
||||||
const resetArenaState = isNewBiome || this.currentBattle.battleType === BattleType.TRAINER || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS;
|
const resetArenaState = (isNewBiome || this.currentBattle.battleType === BattleType.TRAINER || [ BattleSpec.FINAL_BOSS, BattleSpec.NUZLOCKE_BOSS ].includes(this.currentBattle.battleSpec)) && !this.gameMode.hasNoReturns;
|
||||||
this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
|
this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy());
|
||||||
this.trySpreadPokerus();
|
this.trySpreadPokerus();
|
||||||
if (!isNewBiome && (newWaveIndex % 10) == 5)
|
if (!isNewBiome && (newWaveIndex % 10) == 5)
|
||||||
|
@ -1373,10 +1379,10 @@ export default class BattleScene extends SceneBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playSoundWithoutBgm(soundName: string, pauseDuration?: integer): AnySound {
|
playSoundWithoutBgm(soundName: string, pauseDuration?: integer, config?: object): AnySound {
|
||||||
this.bgmCache.add(soundName);
|
this.bgmCache.add(soundName);
|
||||||
const resumeBgm = this.pauseBgm();
|
const resumeBgm = this.pauseBgm();
|
||||||
this.playSound(soundName);
|
this.playSound(soundName, config);
|
||||||
const sound = this.sound.get(soundName) as AnySound;
|
const sound = this.sound.get(soundName) as AnySound;
|
||||||
if (this.bgmResumeTimer)
|
if (this.bgmResumeTimer)
|
||||||
this.bgmResumeTimer.destroy();
|
this.bgmResumeTimer.destroy();
|
||||||
|
@ -1933,4 +1939,16 @@ export default class BattleScene extends SceneBase {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateGameInfo(): void {
|
||||||
|
const gameInfo = {
|
||||||
|
gameMode: this.currentBattle ? this.gameMode.getName() : 'Title',
|
||||||
|
biome: this.currentBattle ? getBiomeName(this.arena.biomeType) : '',
|
||||||
|
wave: this.currentBattle?.waveIndex || 0,
|
||||||
|
party: this.party ? this.party.map(p => {
|
||||||
|
return { name: p.name, level: p.level };
|
||||||
|
}) : []
|
||||||
|
};
|
||||||
|
(window as any).gameInfo = gameInfo;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -92,7 +92,7 @@ export default class Battle {
|
||||||
let spec = BattleSpec.DEFAULT;
|
let spec = BattleSpec.DEFAULT;
|
||||||
if (this.gameMode.isClassic) {
|
if (this.gameMode.isClassic) {
|
||||||
if (this.waveIndex === 200)
|
if (this.waveIndex === 200)
|
||||||
spec = BattleSpec.FINAL_BOSS;
|
spec = !this.gameMode.isNuzlocke ? BattleSpec.FINAL_BOSS : BattleSpec.NUZLOCKE_BOSS;
|
||||||
}
|
}
|
||||||
this.battleSpec = spec;
|
this.battleSpec = spec;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ export default class Battle {
|
||||||
if (!this.started && this.trainer.config.encounterBgm && this.trainer.getEncounterMessages()?.length)
|
if (!this.started && this.trainer.config.encounterBgm && this.trainer.getEncounterMessages()?.length)
|
||||||
return `encounter_${this.trainer.getEncounterBgm()}`;
|
return `encounter_${this.trainer.getEncounterBgm()}`;
|
||||||
return this.trainer.getBattleBgm();
|
return this.trainer.getBattleBgm();
|
||||||
} else if (this.gameMode.isClassic && this.waveIndex > 195 && this.battleSpec !== BattleSpec.FINAL_BOSS)
|
} else if (this.gameMode.isClassic && this.waveIndex > 195 && ![ BattleSpec.FINAL_BOSS, BattleSpec.NUZLOCKE_BOSS ].includes(this.battleSpec))
|
||||||
return 'end_summit';
|
return 'end_summit';
|
||||||
for (let pokemon of battlers) {
|
for (let pokemon of battlers) {
|
||||||
if (this.battleSpec === BattleSpec.FINAL_BOSS) {
|
if (this.battleSpec === BattleSpec.FINAL_BOSS) {
|
||||||
|
@ -256,6 +256,7 @@ export class FixedBattleConfig {
|
||||||
public getTrainer: GetTrainerFunc;
|
public getTrainer: GetTrainerFunc;
|
||||||
public getEnemyParty: GetEnemyPartyFunc;
|
public getEnemyParty: GetEnemyPartyFunc;
|
||||||
public seedOffsetWaveIndex: integer;
|
public seedOffsetWaveIndex: integer;
|
||||||
|
public condition: (scene: BattleScene) => boolean;
|
||||||
|
|
||||||
setBattleType(battleType: BattleType): FixedBattleConfig {
|
setBattleType(battleType: BattleType): FixedBattleConfig {
|
||||||
this.battleType = battleType;
|
this.battleType = battleType;
|
||||||
|
@ -281,6 +282,11 @@ export class FixedBattleConfig {
|
||||||
this.seedOffsetWaveIndex = seedOffsetWaveIndex;
|
this.seedOffsetWaveIndex = seedOffsetWaveIndex;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCondition(condition: (scene: BattleScene) => boolean): FixedBattleConfig {
|
||||||
|
this.condition = condition;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): GetTrainerFunc {
|
function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[]): GetTrainerFunc {
|
||||||
|
@ -325,5 +331,8 @@ export const fixedBattles: FixedBattleConfigs = {
|
||||||
[190]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
|
[190]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
|
||||||
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN, TrainerType.LEON ])),
|
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN, TrainerType.LEON ])),
|
||||||
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
|
||||||
|
[200]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
|
||||||
|
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.NUZLEAF, TrainerVariant.DEFAULT))
|
||||||
|
.setCondition(scene => scene.gameMode.isNuzlocke)
|
||||||
};
|
};
|
|
@ -2269,7 +2269,12 @@ export const trainerTypeDialogue = {
|
||||||
$@c{smile_ehalf}…Thank you.`
|
$@c{smile_ehalf}…Thank you.`
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
[TrainerType.NUZLEAF]: {
|
||||||
|
encounter: [
|
||||||
|
`You've done well to make it this far.\nI am Nuzleaf, and this is your final test.`
|
||||||
]
|
]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const battleSpecDialogue = {
|
export const battleSpecDialogue = {
|
||||||
|
|
|
@ -180,5 +180,6 @@ export enum TrainerType {
|
||||||
RIVAL_3,
|
RIVAL_3,
|
||||||
RIVAL_4,
|
RIVAL_4,
|
||||||
RIVAL_5,
|
RIVAL_5,
|
||||||
RIVAL_6
|
RIVAL_6,
|
||||||
|
NUZLEAF = 400
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { TrainerType } from "./enums/trainer-type";
|
||||||
import { Moves } from "./enums/moves";
|
import { Moves } from "./enums/moves";
|
||||||
import { PokeballType } from "./pokeball";
|
import { PokeballType } from "./pokeball";
|
||||||
import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
|
import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
|
||||||
import PokemonSpecies, { PokemonSpeciesFilter, getPokemonSpecies } from "./pokemon-species";
|
import PokemonSpecies, { PokemonSpeciesFilter, SpeciesFormKey, getPokemonSpecies } from "./pokemon-species";
|
||||||
import { Species } from "./enums/species";
|
import { Species } from "./enums/species";
|
||||||
import { tmSpecies } from "./tms";
|
import { tmSpecies } from "./tms";
|
||||||
import { Type } from "./type";
|
import { Type } from "./type";
|
||||||
|
@ -155,7 +155,9 @@ export const trainerPartyTemplates = {
|
||||||
RIVAL_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)),
|
RIVAL_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)),
|
||||||
RIVAL_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)),
|
RIVAL_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.WEAK, false, true)),
|
||||||
RIVAL_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)),
|
RIVAL_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)),
|
||||||
RIVAL_6: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER))
|
RIVAL_6: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.STRONG), new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, PartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, PartyMemberStrength.STRONGER)),
|
||||||
|
|
||||||
|
NUZLEAF: new TrainerPartyTemplate(1, PartyMemberStrength.STRONG, false, true)//new TrainerPartyTemplate(5, PartyMemberStrength.STRONG, false, true),
|
||||||
};
|
};
|
||||||
|
|
||||||
type PartyTemplateFunc = (scene: BattleScene) => TrainerPartyTemplate;
|
type PartyTemplateFunc = (scene: BattleScene) => TrainerPartyTemplate;
|
||||||
|
@ -867,11 +869,45 @@ export const trainerConfigs: TrainerConfigs = {
|
||||||
p.shiny = true;
|
p.shiny = true;
|
||||||
p.variant = 1;
|
p.variant = 1;
|
||||||
p.formIndex = 1;
|
p.formIndex = 1;
|
||||||
|
p.generateName();
|
||||||
}))
|
}))
|
||||||
.setGenModifiersFunc(party => {
|
.setGenModifiersFunc(party => {
|
||||||
const starter = party[0];
|
const starter = party[0];
|
||||||
return [ modifierTypes.TERA_SHARD().generateType(null, [ starter.species.type1 ]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ];
|
return [ modifierTypes.TERA_SHARD().generateType(null, [ starter.species.type1 ]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ];
|
||||||
}),
|
}),
|
||||||
|
[TrainerType.NUZLEAF]: new TrainerConfig((t = TrainerType.NUZLEAF)).setName('Nuzleaf').setBoss().setEncounterBgm('final').setBattleBgm('battle_final').setPartyTemplates(trainerPartyTemplates.NUZLEAF)
|
||||||
|
.setPartyMemberFunc(0, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => species.baseTotal >= 540, TrainerSlot.TRAINER, false,
|
||||||
|
(p => {
|
||||||
|
p.level = 200;
|
||||||
|
p.setBoss(true, 1);
|
||||||
|
})))
|
||||||
|
.setPartyMemberFunc(1, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => species.baseTotal >= 540, TrainerSlot.TRAINER, false,
|
||||||
|
(p => {
|
||||||
|
p.level = 200;
|
||||||
|
p.setBoss(true, 1);
|
||||||
|
})))
|
||||||
|
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && species.forms.some(f => f.formKey.includes(SpeciesFormKey.MEGA)), TrainerSlot.TRAINER, false,
|
||||||
|
(p => {
|
||||||
|
p.level = 200;
|
||||||
|
p.formIndex = p.species.forms.findIndex(f => f.formKey.includes(SpeciesFormKey.MEGA));
|
||||||
|
p.setBoss(true, 2);
|
||||||
|
p.generateName();
|
||||||
|
})
|
||||||
|
))
|
||||||
|
.setPartyMemberFunc(3, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && species.forms.some(f => f.formKey.includes(SpeciesFormKey.GIGANTAMAX)), TrainerSlot.TRAINER, false,
|
||||||
|
(p => {
|
||||||
|
p.level = 200;
|
||||||
|
p.formIndex = p.species.forms.findIndex(f => f.formKey.includes(SpeciesFormKey.GIGANTAMAX));
|
||||||
|
p.setBoss(true, 2);
|
||||||
|
p.generateName();
|
||||||
|
})
|
||||||
|
))
|
||||||
|
.setPartyMemberFunc(4, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => species.baseTotal >= 540, TrainerSlot.TRAINER, false,
|
||||||
|
(p => {
|
||||||
|
p.level = 200;
|
||||||
|
p.setBoss(true, 1);
|
||||||
|
})))
|
||||||
|
.setSpeciesFilter(species => species.baseTotal >= 540)
|
||||||
};
|
};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export enum BattleSpec {
|
export enum BattleSpec {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
FINAL_BOSS
|
FINAL_BOSS,
|
||||||
|
NUZLOCKE_BOSS
|
||||||
}
|
}
|
||||||
|
|
|
@ -1702,17 +1702,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
return cry;
|
return cry;
|
||||||
}
|
}
|
||||||
|
|
||||||
faintCry(callback: Function): void {
|
faintCry(callback: Function, forPermadeath: boolean = false): void {
|
||||||
if (this.fusionSpecies)
|
if (this.fusionSpecies)
|
||||||
return this.fusionFaintCry(callback);
|
return this.fusionFaintCry(callback, forPermadeath);
|
||||||
|
|
||||||
const key = this.getSpeciesForm().getCryKey(this.formIndex);
|
const key = this.getSpeciesForm().getCryKey(this.formIndex);
|
||||||
let i = 0;
|
|
||||||
let rate = 0.85;
|
let rate = 0.85;
|
||||||
const cry = this.scene.playSound(key, { rate: rate }) as AnySound;
|
const cry = (!forPermadeath
|
||||||
|
? this.scene.playSound(key, { rate: rate })
|
||||||
|
: this.scene.playSoundWithoutBgm(key, Utils.fixedInt(2500), { rate: rate })) as AnySound;
|
||||||
const sprite = this.getSprite();
|
const sprite = this.getSprite();
|
||||||
const tintSprite = this.getTintSprite();
|
const tintSprite = this.getTintSprite();
|
||||||
|
|
||||||
|
const decayRate = !forPermadeath ? 0.99 : 0.98;
|
||||||
const delay = Math.max(this.scene.sound.get(key).totalDuration * 50, 25);
|
const delay = Math.max(this.scene.sound.get(key).totalDuration * 50, 25);
|
||||||
|
|
||||||
let frameProgress = 0;
|
let frameProgress = 0;
|
||||||
|
@ -1721,11 +1723,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
sprite.anims.pause();
|
sprite.anims.pause();
|
||||||
tintSprite.anims.pause();
|
tintSprite.anims.pause();
|
||||||
|
|
||||||
|
if (forPermadeath)
|
||||||
|
this.tint(0, 0.325, Utils.fixedInt(1500), 'Sine.easeIn');
|
||||||
|
|
||||||
let faintCryTimer = this.scene.time.addEvent({
|
let faintCryTimer = this.scene.time.addEvent({
|
||||||
delay: Utils.fixedInt(delay),
|
delay: Utils.fixedInt(delay),
|
||||||
repeat: -1,
|
repeat: -1,
|
||||||
callback: () => {
|
callback: () => {
|
||||||
++i;
|
|
||||||
frameThreshold = sprite.anims.msPerFrame / rate;
|
frameThreshold = sprite.anims.msPerFrame / rate;
|
||||||
frameProgress += delay;
|
frameProgress += delay;
|
||||||
while (frameProgress > frameThreshold) {
|
while (frameProgress > frameThreshold) {
|
||||||
|
@ -1736,7 +1740,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
frameProgress -= frameThreshold;
|
frameProgress -= frameThreshold;
|
||||||
}
|
}
|
||||||
if (cry && !cry.pendingRemove) {
|
if (cry && !cry.pendingRemove) {
|
||||||
rate *= 0.99;
|
rate *= decayRate;
|
||||||
cry.setRate(rate);
|
cry.setRate(rate);
|
||||||
} else {
|
} else {
|
||||||
faintCryTimer.destroy();
|
faintCryTimer.destroy();
|
||||||
|
@ -1759,13 +1763,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private fusionFaintCry(callback: Function): void {
|
private fusionFaintCry(callback: Function, forPermadeath: boolean = false): void {
|
||||||
const key = this.getSpeciesForm().getCryKey(this.formIndex);
|
const key = this.getSpeciesForm().getCryKey(this.formIndex);
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let rate = 0.85;
|
let rate = 0.85;
|
||||||
let cry = this.scene.playSound(key, { rate: rate }) as AnySound;
|
let cry = (!forPermadeath
|
||||||
|
? this.scene.playSound(key, { rate: rate })
|
||||||
|
: this.scene.playSoundWithoutBgm(key, Utils.fixedInt(2000), { rate: rate })) as AnySound;
|
||||||
const sprite = this.getSprite();
|
const sprite = this.getSprite();
|
||||||
const tintSprite = this.getTintSprite();
|
const tintSprite = this.getTintSprite();
|
||||||
|
|
||||||
|
const decayRate = !forPermadeath ? 0.99 : 0.98;
|
||||||
let duration = cry.totalDuration * 1000;
|
let duration = cry.totalDuration * 1000;
|
||||||
|
|
||||||
let fusionCry = this.scene.playSound(this.getFusionSpeciesForm().getCryKey(this.fusionFormIndex), { rate: rate }) as AnySound;
|
let fusionCry = this.scene.playSound(this.getFusionSpeciesForm().getCryKey(this.fusionFormIndex), { rate: rate }) as AnySound;
|
||||||
|
@ -1782,7 +1790,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
while (durationProgress < transitionThreshold) {
|
while (durationProgress < transitionThreshold) {
|
||||||
++i;
|
++i;
|
||||||
durationProgress += delay * rate;
|
durationProgress += delay * rate;
|
||||||
rate *= 0.99;
|
rate *= decayRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
transitionIndex = i;
|
transitionIndex = i;
|
||||||
|
@ -1796,6 +1804,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
sprite.anims.pause();
|
sprite.anims.pause();
|
||||||
tintSprite.anims.pause();
|
tintSprite.anims.pause();
|
||||||
|
|
||||||
|
if (forPermadeath)
|
||||||
|
this.tint(0, 0.325, Utils.fixedInt(1500), 'Sine.easeIn');
|
||||||
|
|
||||||
let faintCryTimer = this.scene.time.addEvent({
|
let faintCryTimer = this.scene.time.addEvent({
|
||||||
delay: Utils.fixedInt(delay),
|
delay: Utils.fixedInt(delay),
|
||||||
repeat: -1,
|
repeat: -1,
|
||||||
|
@ -1815,7 +1826,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
fusionCry = this.scene.playSound(this.getFusionSpeciesForm().getCryKey(this.fusionFormIndex), Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0), rate: rate }));
|
fusionCry = this.scene.playSound(this.getFusionSpeciesForm().getCryKey(this.fusionFormIndex), Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0), rate: rate }));
|
||||||
SoundFade.fadeIn(this.scene, fusionCry, Utils.fixedInt(Math.ceil((duration / rate) * 0.2)), this.scene.masterVolume * this.scene.seVolume, 0);
|
SoundFade.fadeIn(this.scene, fusionCry, Utils.fixedInt(Math.ceil((duration / rate) * 0.2)), this.scene.masterVolume * this.scene.seVolume, 0);
|
||||||
}
|
}
|
||||||
rate *= 0.99;
|
rate *= decayRate;
|
||||||
if (cry && !cry.pendingRemove)
|
if (cry && !cry.pendingRemove)
|
||||||
cry.setRate(rate);
|
cry.setRate(rate);
|
||||||
if (fusionCry && !fusionCry.pendingRemove)
|
if (fusionCry && !fusionCry.pendingRemove)
|
||||||
|
@ -2649,7 +2660,7 @@ export class EnemyPokemon extends Pokemon {
|
||||||
|
|
||||||
this.trainerSlot = trainerSlot;
|
this.trainerSlot = trainerSlot;
|
||||||
if (boss)
|
if (boss)
|
||||||
this.setBoss();
|
this.setBoss(true, dataSource?.bossSegments);
|
||||||
|
|
||||||
if (!dataSource) {
|
if (!dataSource) {
|
||||||
this.generateAndPopulateMoveset();
|
this.generateAndPopulateMoveset();
|
||||||
|
|
|
@ -184,10 +184,12 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
genPartyMember(index: integer): EnemyPokemon {
|
genPartyMember(index: integer, retryCount: integer = 0): EnemyPokemon {
|
||||||
const battle = this.scene.currentBattle;
|
const battle = this.scene.currentBattle;
|
||||||
const level = battle.enemyLevels[index];
|
const level = battle.enemyLevels[index];
|
||||||
|
|
||||||
|
let retry = false;
|
||||||
|
|
||||||
let ret: EnemyPokemon;
|
let ret: EnemyPokemon;
|
||||||
|
|
||||||
this.scene.executeWithSeedOffset(() => {
|
this.scene.executeWithSeedOffset(() => {
|
||||||
|
@ -196,10 +198,20 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
if (this.config.partyMemberFuncs.hasOwnProperty(index)) {
|
if (this.config.partyMemberFuncs.hasOwnProperty(index)) {
|
||||||
ret = this.config.partyMemberFuncs[index](this.scene, level, strength);
|
ret = this.config.partyMemberFuncs[index](this.scene, level, strength);
|
||||||
|
if (template.isBalanced(index)) {
|
||||||
|
const partyMemberTypes = battle.enemyParty.map(p => p.getTypes(true)).flat();
|
||||||
|
if (partyMemberTypes.indexOf(ret.species.type1) > -1 || (ret.species.type2 !== null && partyMemberTypes.indexOf(ret.species.type2) > -1))
|
||||||
|
retry = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.config.partyMemberFuncs.hasOwnProperty(index - template.size)) {
|
if (this.config.partyMemberFuncs.hasOwnProperty(index - template.size)) {
|
||||||
ret = this.config.partyMemberFuncs[index - template.size](this.scene, level, template.getStrength(index));
|
ret = this.config.partyMemberFuncs[index - template.size](this.scene, level, strength);
|
||||||
|
if (template.isBalanced(index - template.size)) {
|
||||||
|
const partyMemberTypes = battle.enemyParty.map(p => p.getTypes(true)).flat();
|
||||||
|
if (partyMemberTypes.indexOf(ret.species.type1) > -1 || (ret.species.type2 !== null && partyMemberTypes.indexOf(ret.species.type2) > -1))
|
||||||
|
retry = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +230,10 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
: this.genNewPartyMemberSpecies(level, strength);
|
: this.genNewPartyMemberSpecies(level, strength);
|
||||||
|
|
||||||
ret = this.scene.addEnemyPokemon(species, level, !this.isDouble() || !(index % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER);
|
ret = this.scene.addEnemyPokemon(species, level, !this.isDouble() || !(index % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER);
|
||||||
}, this.config.hasStaticParty ? this.config.getDerivedType() + ((index + 1) << 8) : this.scene.currentBattle.waveIndex + (this.config.getDerivedType() << 10) + (((!this.config.useSameSeedForAllMembers ? index : 0) + 1) << 8));
|
}, this.config.hasStaticParty ? this.config.getDerivedType() + ((index + 1 + retryCount * 6) << 8) : this.scene.currentBattle.waveIndex + (this.config.getDerivedType() << 10) + (((!this.config.useSameSeedForAllMembers ? index : 0) + 1 + retryCount * 6) << 8));
|
||||||
|
|
||||||
|
if (retry && ++retryCount < 10)
|
||||||
|
return this.genPartyMember(index, retryCount);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -311,7 +326,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
getNextSummonIndex(trainerSlot: TrainerSlot = TrainerSlot.NONE, partyMemberScores: [integer, integer][] = this.getPartyMemberMatchupScores(trainerSlot)): integer {
|
getNextSummonIndex(trainerSlot: TrainerSlot = TrainerSlot.NONE, partyMemberScores: [integer, integer][] = this.getPartyMemberMatchupScores(trainerSlot)): integer {
|
||||||
if (trainerSlot && !this.isDouble())
|
if (trainerSlot && !this.isDouble() || !this.config.hasGenders)
|
||||||
trainerSlot = TrainerSlot.NONE;
|
trainerSlot = TrainerSlot.NONE;
|
||||||
|
|
||||||
const sortedPartyMemberScores = this.getSortedPartyMemberMatchupScores(partyMemberScores);
|
const sortedPartyMemberScores = this.getSortedPartyMemberMatchupScores(partyMemberScores);
|
||||||
|
|
|
@ -11,16 +11,23 @@ export enum GameModes {
|
||||||
CLASSIC,
|
CLASSIC,
|
||||||
ENDLESS,
|
ENDLESS,
|
||||||
SPLICED_ENDLESS,
|
SPLICED_ENDLESS,
|
||||||
DAILY
|
DAILY,
|
||||||
|
NUZLOCKE,
|
||||||
|
GAUNTLET
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GameModeConfig {
|
interface GameModeConfig {
|
||||||
isClassic?: boolean;
|
isClassic?: boolean;
|
||||||
isEndless?: boolean;
|
isEndless?: boolean;
|
||||||
isDaily?: boolean;
|
isDaily?: boolean;
|
||||||
|
isNuzlocke?: boolean;
|
||||||
|
hasNoHeals?: boolean;
|
||||||
|
hasNoReturns?: boolean;
|
||||||
hasTrainers?: boolean;
|
hasTrainers?: boolean;
|
||||||
hasFixedBattles?: boolean;
|
hasFixedBattles?: boolean;
|
||||||
hasNoShop?: boolean;
|
hasNoShop?: boolean;
|
||||||
|
hasStrictLevelCap?: boolean;
|
||||||
|
hasPassiveHeals?: boolean;
|
||||||
hasShortBiomes?: boolean;
|
hasShortBiomes?: boolean;
|
||||||
hasRandomBiomes?: boolean;
|
hasRandomBiomes?: boolean;
|
||||||
hasRandomBosses?: boolean;
|
hasRandomBosses?: boolean;
|
||||||
|
@ -32,9 +39,14 @@ export class GameMode implements GameModeConfig {
|
||||||
public isClassic: boolean;
|
public isClassic: boolean;
|
||||||
public isEndless: boolean;
|
public isEndless: boolean;
|
||||||
public isDaily: boolean;
|
public isDaily: boolean;
|
||||||
|
public isNuzlocke: boolean;
|
||||||
|
public hasNoHeals: boolean;
|
||||||
|
public hasNoReturns: boolean;
|
||||||
public hasTrainers: boolean;
|
public hasTrainers: boolean;
|
||||||
public hasFixedBattles: boolean;
|
public hasFixedBattles: boolean;
|
||||||
public hasNoShop: boolean;
|
public hasNoShop: boolean;
|
||||||
|
public hasStrictLevelCap: boolean;
|
||||||
|
public hasPassiveHeals: boolean;
|
||||||
public hasShortBiomes: boolean;
|
public hasShortBiomes: boolean;
|
||||||
public hasRandomBiomes: boolean;
|
public hasRandomBiomes: boolean;
|
||||||
public hasRandomBosses: boolean;
|
public hasRandomBosses: boolean;
|
||||||
|
@ -78,9 +90,10 @@ export class GameMode implements GameModeConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isWaveTrainer(waveIndex: integer, arena: Arena): boolean {
|
isWaveTrainer(waveIndex: integer, scene: BattleScene): boolean {
|
||||||
if (this.isDaily)
|
if (this.isDaily)
|
||||||
return waveIndex % 10 === 5 || (!(waveIndex % 10) && waveIndex > 10 && !this.isWaveFinal(waveIndex));
|
return waveIndex % 10 === 5 || (!(waveIndex % 10) && waveIndex > 10 && !this.isWaveFinal(waveIndex));
|
||||||
|
const arena = scene.arena;
|
||||||
if ((waveIndex % 30) === (arena.scene.offsetGym ? 0 : 20) && !this.isWaveFinal(waveIndex))
|
if ((waveIndex % 30) === (arena.scene.offsetGym ? 0 : 20) && !this.isWaveFinal(waveIndex))
|
||||||
return true;
|
return true;
|
||||||
else if (waveIndex % 10 !== 1 && waveIndex % 10) {
|
else if (waveIndex % 10 !== 1 && waveIndex % 10) {
|
||||||
|
@ -91,7 +104,7 @@ export class GameMode implements GameModeConfig {
|
||||||
for (let w = Math.max(waveIndex - 3, waveBase + 2); w <= Math.min(waveIndex + 3, waveBase + 9); w++) {
|
for (let w = Math.max(waveIndex - 3, waveBase + 2); w <= Math.min(waveIndex + 3, waveBase + 9); w++) {
|
||||||
if (w === waveIndex)
|
if (w === waveIndex)
|
||||||
continue;
|
continue;
|
||||||
if ((w % 30) === (arena.scene.offsetGym ? 0 : 20) || fixedBattles.hasOwnProperty(w)) {
|
if ((w % 30) === (arena.scene.offsetGym ? 0 : 20) || (fixedBattles.hasOwnProperty(w) && fixedBattles[w].condition(scene))) {
|
||||||
allowTrainerBattle = false;
|
allowTrainerBattle = false;
|
||||||
break;
|
break;
|
||||||
} else if (w < waveIndex) {
|
} else if (w < waveIndex) {
|
||||||
|
@ -132,9 +145,11 @@ export class GameMode implements GameModeConfig {
|
||||||
isWaveFinal(waveIndex: integer): boolean {
|
isWaveFinal(waveIndex: integer): boolean {
|
||||||
switch (this.modeId) {
|
switch (this.modeId) {
|
||||||
case GameModes.CLASSIC:
|
case GameModes.CLASSIC:
|
||||||
|
case GameModes.NUZLOCKE:
|
||||||
return waveIndex === 200;
|
return waveIndex === 200;
|
||||||
case GameModes.ENDLESS:
|
case GameModes.ENDLESS:
|
||||||
case GameModes.SPLICED_ENDLESS:
|
case GameModes.SPLICED_ENDLESS:
|
||||||
|
case GameModes.GAUNTLET:
|
||||||
return !(waveIndex % 250);
|
return !(waveIndex % 250);
|
||||||
case GameModes.DAILY:
|
case GameModes.DAILY:
|
||||||
return waveIndex === 50;
|
return waveIndex === 50;
|
||||||
|
@ -154,9 +169,11 @@ export class GameMode implements GameModeConfig {
|
||||||
switch (this.modeId) {
|
switch (this.modeId) {
|
||||||
case GameModes.CLASSIC:
|
case GameModes.CLASSIC:
|
||||||
case GameModes.DAILY:
|
case GameModes.DAILY:
|
||||||
|
case GameModes.NUZLOCKE:
|
||||||
return !isBoss ? 18 : 6;
|
return !isBoss ? 18 : 6;
|
||||||
case GameModes.ENDLESS:
|
case GameModes.ENDLESS:
|
||||||
case GameModes.SPLICED_ENDLESS:
|
case GameModes.SPLICED_ENDLESS:
|
||||||
|
case GameModes.GAUNTLET:
|
||||||
return !isBoss ? 12 : 4;
|
return !isBoss ? 12 : 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,6 +188,10 @@ export class GameMode implements GameModeConfig {
|
||||||
return 'Endless (Spliced)';
|
return 'Endless (Spliced)';
|
||||||
case GameModes.DAILY:
|
case GameModes.DAILY:
|
||||||
return 'Daily Run';
|
return 'Daily Run';
|
||||||
|
case GameModes.NUZLOCKE:
|
||||||
|
return 'Nuzlocke';
|
||||||
|
case GameModes.GAUNTLET:
|
||||||
|
return 'Gauntlet';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,5 +200,7 @@ export const gameModes = Object.freeze({
|
||||||
[GameModes.CLASSIC]: new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasFixedBattles: true }),
|
[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.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.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 })
|
[GameModes.DAILY]: new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }),
|
||||||
|
[GameModes.NUZLOCKE]: new GameMode(GameModes.NUZLOCKE, { isClassic: true, isNuzlocke: true, hasStrictLevelCap: true, hasTrainers: true, hasFixedBattles: true }),
|
||||||
|
[GameModes.GAUNTLET]: new GameMode(GameModes.GAUNTLET, { isEndless: true, hasNoHeals: true, hasNoReturns: true, hasPassiveHeals: true, hasShortBiomes: true, hasRandomBosses: true })
|
||||||
});
|
});
|
|
@ -160,7 +160,7 @@ export class LoadingScene extends SceneBase {
|
||||||
Utils.getEnumValues(TrainerType).map(tt => {
|
Utils.getEnumValues(TrainerType).map(tt => {
|
||||||
const config = trainerConfigs[tt];
|
const config = trainerConfigs[tt];
|
||||||
this.loadAtlas(config.getSpriteKey(), 'trainer');
|
this.loadAtlas(config.getSpriteKey(), 'trainer');
|
||||||
if (config.doubleOnly || config.hasDouble)
|
if ((config.doubleOnly || config.hasDouble) && config.hasGenders)
|
||||||
this.loadAtlas(config.getSpriteKey(true), 'trainer');
|
this.loadAtlas(config.getSpriteKey(true), 'trainer');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -251,6 +251,9 @@ export class LoadingScene extends SceneBase {
|
||||||
this.loadSe('gacha_running');
|
this.loadSe('gacha_running');
|
||||||
this.loadSe('gacha_dispense');
|
this.loadSe('gacha_dispense');
|
||||||
|
|
||||||
|
// Nuzleaf
|
||||||
|
this.loadSe('274', '', '../cry/274.m4a');
|
||||||
|
|
||||||
this.loadSe('PRSFX- Transform', 'battle_anims');
|
this.loadSe('PRSFX- Transform', 'battle_anims');
|
||||||
|
|
||||||
this.loadBgm('menu');
|
this.loadBgm('menu');
|
||||||
|
|
|
@ -9,6 +9,7 @@ export function getPokemonPrefix(pokemon: Pokemon): string {
|
||||||
let prefix: string;
|
let prefix: string;
|
||||||
switch (pokemon.scene.currentBattle.battleSpec) {
|
switch (pokemon.scene.currentBattle.battleSpec) {
|
||||||
case BattleSpec.DEFAULT:
|
case BattleSpec.DEFAULT:
|
||||||
|
case BattleSpec.NUZLOCKE_BOSS:
|
||||||
prefix = !pokemon.isPlayer() ? pokemon.hasTrainer() ? 'Foe ' : 'Wild ' : '';
|
prefix = !pokemon.isPlayer() ? pokemon.hasTrainer() ? 'Foe ' : 'Wild ' : '';
|
||||||
break;
|
break;
|
||||||
case BattleSpec.FINAL_BOSS:
|
case BattleSpec.FINAL_BOSS:
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { AttackMove, allMoves } from '../data/move';
|
||||||
import { Moves } from "../data/enums/moves";
|
import { Moves } from "../data/enums/moves";
|
||||||
import { PokeballType, getPokeballCatchMultiplier, getPokeballName } from '../data/pokeball';
|
import { PokeballType, getPokeballCatchMultiplier, getPokeballName } from '../data/pokeball';
|
||||||
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from '../field/pokemon';
|
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from '../field/pokemon';
|
||||||
import { EvolutionItem, SpeciesFriendshipEvolutionCondition, pokemonEvolutions } from '../data/pokemon-evolutions';
|
import { EvolutionItem, pokemonEvolutions } from '../data/pokemon-evolutions';
|
||||||
import { Stat, getStatName } from '../data/pokemon-stat';
|
import { Stat, getStatName } from '../data/pokemon-stat';
|
||||||
import { tmPoolTiers, tmSpecies } from '../data/tms';
|
import { tmPoolTiers, tmSpecies } from '../data/tms';
|
||||||
import { Type } from '../data/type';
|
import { Type } from '../data/type';
|
||||||
|
@ -21,6 +21,7 @@ import { ModifierTier } from './modifier-tier';
|
||||||
import { Nature, getNatureName, getNatureStatMultiplier } from '#app/data/nature';
|
import { Nature, getNatureName, getNatureStatMultiplier } from '#app/data/nature';
|
||||||
import { Localizable } from '#app/plugins/i18n';
|
import { Localizable } from '#app/plugins/i18n';
|
||||||
import { getModifierTierTextTint } from '#app/ui/text';
|
import { getModifierTierTextTint } from '#app/ui/text';
|
||||||
|
import { GameMode } from '#app/game-mode';
|
||||||
|
|
||||||
const outputModifierData = false;
|
const outputModifierData = false;
|
||||||
const useMaxWeightForOutput = false;
|
const useMaxWeightForOutput = false;
|
||||||
|
@ -427,7 +428,11 @@ export class AttackTypeBoosterModifierType extends PokemonHeldItemModifierType i
|
||||||
export class PokemonLevelIncrementModifierType extends PokemonModifierType {
|
export class PokemonLevelIncrementModifierType extends PokemonModifierType {
|
||||||
constructor(name: string, iconImage?: string) {
|
constructor(name: string, iconImage?: string) {
|
||||||
super(name, `Increases a Pokémon\'s level by 1`, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id),
|
super(name, `Increases a Pokémon\'s level by 1`, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id),
|
||||||
(_pokemon: PlayerPokemon) => null, iconImage);
|
(pokemon: PlayerPokemon) => {
|
||||||
|
if (pokemon.scene.gameMode.hasStrictLevelCap && pokemon.level >= pokemon.scene.getMaxExpLevel())
|
||||||
|
return PartyUiHandler.NoEffectMessage;
|
||||||
|
return null;
|
||||||
|
}, iconImage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,14 +1000,20 @@ const modifierPool: ModifierPool = {
|
||||||
return statusEffectPartyMemberCount * 6;
|
return statusEffectPartyMemberCount * 6;
|
||||||
}, 18),
|
}, 18),
|
||||||
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.REVIVE, (party: Pokemon[]) => {
|
||||||
|
if (party[0].scene.gameMode.isNuzlocke)
|
||||||
|
return 0;
|
||||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||||
return faintedPartyMemberCount * 9;
|
return faintedPartyMemberCount * 9;
|
||||||
}, 3),
|
}, 3),
|
||||||
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.MAX_REVIVE, (party: Pokemon[]) => {
|
||||||
|
if (party[0].scene.gameMode.isNuzlocke)
|
||||||
|
return 0;
|
||||||
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
const faintedPartyMemberCount = Math.min(party.filter(p => p.isFainted()).length, 3);
|
||||||
return faintedPartyMemberCount * 3;
|
return faintedPartyMemberCount * 3;
|
||||||
}, 9),
|
}, 9),
|
||||||
new WeightedModifierType(modifierTypes.SACRED_ASH, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.SACRED_ASH, (party: Pokemon[]) => {
|
||||||
|
if (party[0].scene.gameMode.isNuzlocke)
|
||||||
|
return 0;
|
||||||
return party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
return party.filter(p => p.isFainted()).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
||||||
}, 1),
|
}, 1),
|
||||||
new WeightedModifierType(modifierTypes.HYPER_POTION, (party: Pokemon[]) => {
|
new WeightedModifierType(modifierTypes.HYPER_POTION, (party: Pokemon[]) => {
|
||||||
|
@ -1053,7 +1064,7 @@ const modifierPool: ModifierPool = {
|
||||||
new WeightedModifierType(modifierTypes.MINT, 4),
|
new WeightedModifierType(modifierTypes.MINT, 4),
|
||||||
new WeightedModifierType(modifierTypes.RARE_EVOLUTION_ITEM, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15) * 4, 32), 32),
|
new WeightedModifierType(modifierTypes.RARE_EVOLUTION_ITEM, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15) * 4, 32), 32),
|
||||||
new WeightedModifierType(modifierTypes.AMULET_COIN, 3),
|
new WeightedModifierType(modifierTypes.AMULET_COIN, 3),
|
||||||
new WeightedModifierType(modifierTypes.REVIVER_SEED, 4),
|
new WeightedModifierType(modifierTypes.REVIVER_SEED, (party: Pokemon[]) => party[0].scene.gameMode.isNuzlocke ? 8 : 4, 4),
|
||||||
new WeightedModifierType(modifierTypes.CANDY_JAR, 5),
|
new WeightedModifierType(modifierTypes.CANDY_JAR, 5),
|
||||||
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
|
||||||
new WeightedModifierType(modifierTypes.TM_ULTRA, 8),
|
new WeightedModifierType(modifierTypes.TM_ULTRA, 8),
|
||||||
|
@ -1331,7 +1342,7 @@ export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemo
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, baseCost: integer): ModifierTypeOption[] {
|
export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, baseCost: integer, gameMode: GameMode): ModifierTypeOption[] {
|
||||||
if (!(waveIndex % 10))
|
if (!(waveIndex % 10))
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
|
@ -1339,7 +1350,7 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.POTION(), 0, baseCost * 0.2),
|
new ModifierTypeOption(modifierTypes.POTION(), 0, baseCost * 0.2),
|
||||||
new ModifierTypeOption(modifierTypes.ETHER(), 0, baseCost * 0.4),
|
new ModifierTypeOption(modifierTypes.ETHER(), 0, baseCost * 0.4),
|
||||||
new ModifierTypeOption(modifierTypes.REVIVE(), 0, baseCost * 2)
|
!gameMode.isNuzlocke ? new ModifierTypeOption(modifierTypes.REVIVE(), 0, baseCost * 2) : null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.SUPER_POTION(), 0, baseCost * 0.45),
|
new ModifierTypeOption(modifierTypes.SUPER_POTION(), 0, baseCost * 0.45),
|
||||||
|
@ -1351,7 +1362,7 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8),
|
new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8),
|
||||||
new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75)
|
!gameMode.isNuzlocke ? new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75) : null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5),
|
new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5),
|
||||||
|
@ -1361,10 +1372,10 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base
|
||||||
new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)
|
new ModifierTypeOption(modifierTypes.FULL_RESTORE(), 0, baseCost * 2.25)
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10)
|
!gameMode.isNuzlocke ? new ModifierTypeOption(modifierTypes.SACRED_ASH(), 0, baseCost * 10) : null
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat();
|
return options.slice(0, Math.ceil(Math.max(waveIndex + 10, 0) / 30)).flat().filter(o => o);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: Modifiers.PersistentModifier[], scene: BattleScene): Modifiers.EnemyPersistentModifier {
|
export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: Modifiers.PersistentModifier[], scene: BattleScene): Modifiers.EnemyPersistentModifier {
|
||||||
|
|
|
@ -885,7 +885,14 @@ export class BerryModifier extends PokemonHeldItemModifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
||||||
return 10;
|
switch (this.berryType) {
|
||||||
|
case BerryType.LUM:
|
||||||
|
case BerryType.LEPPA:
|
||||||
|
case BerryType.SITRUS:
|
||||||
|
case BerryType.ENIGMA:
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,6 +994,8 @@ export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
|
||||||
apply(args: any[]): boolean {
|
apply(args: any[]): boolean {
|
||||||
const pokemon = args[0] as Pokemon;
|
const pokemon = args[0] as Pokemon;
|
||||||
if (!pokemon.hp === this.fainted) {
|
if (!pokemon.hp === this.fainted) {
|
||||||
|
if (this.fainted)
|
||||||
|
pokemon.scene.reviveCount++;
|
||||||
let restorePoints = this.restorePoints;
|
let restorePoints = this.restorePoints;
|
||||||
if (!this.fainted)
|
if (!this.fainted)
|
||||||
restorePoints = Math.floor(restorePoints * (args[1] as number));
|
restorePoints = Math.floor(restorePoints * (args[1] as number));
|
||||||
|
|
125
src/phases.ts
125
src/phases.ts
|
@ -192,7 +192,6 @@ export class TitlePhase extends Phase {
|
||||||
this.scene.ui.clearText();
|
this.scene.ui.clearText();
|
||||||
this.end();
|
this.end();
|
||||||
};
|
};
|
||||||
if (this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]) {
|
|
||||||
const options: OptionSelectItem[] = [
|
const options: OptionSelectItem[] = [
|
||||||
{
|
{
|
||||||
label: gameModes[GameModes.CLASSIC].getName(),
|
label: gameModes[GameModes.CLASSIC].getName(),
|
||||||
|
@ -200,15 +199,27 @@ export class TitlePhase extends Phase {
|
||||||
setModeAndEnd(GameModes.CLASSIC);
|
setModeAndEnd(GameModes.CLASSIC);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
{
|
];
|
||||||
|
if (this.scene.gameData.unlocks[Unlockables.NUZLOCKE_MODE] || true) {
|
||||||
|
options.push({
|
||||||
|
label: gameModes[GameModes.NUZLOCKE].getName(),
|
||||||
|
handler: () => {
|
||||||
|
this.scene.playSound('274');
|
||||||
|
setModeAndEnd(GameModes.NUZLOCKE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]) {
|
||||||
|
options.push({
|
||||||
label: gameModes[GameModes.ENDLESS].getName(),
|
label: gameModes[GameModes.ENDLESS].getName(),
|
||||||
handler: () => {
|
handler: () => {
|
||||||
setModeAndEnd(GameModes.ENDLESS);
|
setModeAndEnd(GameModes.ENDLESS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
];
|
|
||||||
if (this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]) {
|
if (this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]) {
|
||||||
options.push({
|
options.push({
|
||||||
label: gameModes[GameModes.SPLICED_ENDLESS].getName(),
|
label: gameModes[GameModes.SPLICED_ENDLESS].getName(),
|
||||||
|
@ -218,6 +229,16 @@ export class TitlePhase extends Phase {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (this.scene.gameData.unlocks[Unlockables.GAUNTLET_MODE]) {
|
||||||
|
options.push({
|
||||||
|
label: gameModes[GameModes.GAUNTLET].getName(),
|
||||||
|
handler: () => {
|
||||||
|
setModeAndEnd(GameModes.GAUNTLET);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (options.length > 1) {
|
||||||
options.push({
|
options.push({
|
||||||
label: i18next.t('menu:cancel'),
|
label: i18next.t('menu:cancel'),
|
||||||
handler: () => {
|
handler: () => {
|
||||||
|
@ -513,7 +534,11 @@ export class SelectStarterPhase extends Phase {
|
||||||
Promise.all(loadPokemonAssets).then(() => {
|
Promise.all(loadPokemonAssets).then(() => {
|
||||||
SoundFade.fadeOut(this.scene, this.scene.sound.get('menu'), 500, true);
|
SoundFade.fadeOut(this.scene, this.scene.sound.get('menu'), 500, true);
|
||||||
this.scene.time.delayedCall(500, () => this.scene.playBgm());
|
this.scene.time.delayedCall(500, () => this.scene.playBgm());
|
||||||
if (this.scene.gameMode.isClassic)
|
if (this.scene.gameMode.isNuzlocke) {
|
||||||
|
this.scene.gameData.gameStats.nuzlockeSessionsPlayed++;
|
||||||
|
this.scene.addModifier(modifierTypes.MAP().withIdFromFunc(modifierTypes.MAP).newModifier(), true, false, false, true);
|
||||||
|
this.scene.updateModifiers(true, true);
|
||||||
|
} else if (this.scene.gameMode.isClassic)
|
||||||
this.scene.gameData.gameStats.classicSessionsPlayed++;
|
this.scene.gameData.gameStats.classicSessionsPlayed++;
|
||||||
else
|
else
|
||||||
this.scene.gameData.gameStats.endlessSessionsPlayed++;
|
this.scene.gameData.gameStats.endlessSessionsPlayed++;
|
||||||
|
@ -678,6 +703,8 @@ export class EncounterPhase extends BattlePhase {
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
this.scene.updateGameInfo();
|
||||||
|
|
||||||
this.scene.initSession();
|
this.scene.initSession();
|
||||||
|
|
||||||
const loadEnemyAssets = [];
|
const loadEnemyAssets = [];
|
||||||
|
@ -713,11 +740,13 @@ export class EncounterPhase extends BattlePhase {
|
||||||
if (this.scene.gameMode.isClassic && (battle.battleSpec === BattleSpec.FINAL_BOSS || this.scene.gameMode.isWaveFinal(battle.waveIndex))) {
|
if (this.scene.gameMode.isClassic && (battle.battleSpec === BattleSpec.FINAL_BOSS || this.scene.gameMode.isWaveFinal(battle.waveIndex))) {
|
||||||
if (battle.battleSpec !== BattleSpec.FINAL_BOSS) {
|
if (battle.battleSpec !== BattleSpec.FINAL_BOSS) {
|
||||||
enemyPokemon.formIndex = 1;
|
enemyPokemon.formIndex = 1;
|
||||||
|
enemyPokemon.calculateStats();
|
||||||
enemyPokemon.updateScale();
|
enemyPokemon.updateScale();
|
||||||
}
|
}
|
||||||
enemyPokemon.setBoss();
|
enemyPokemon.setBoss();
|
||||||
} else if (!(battle.waveIndex % 1000)) {
|
} else if (!(battle.waveIndex % 1000)) {
|
||||||
enemyPokemon.formIndex = 1;
|
enemyPokemon.formIndex = 1;
|
||||||
|
enemyPokemon.calculateStats();
|
||||||
enemyPokemon.updateScale();
|
enemyPokemon.updateScale();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1407,7 +1436,10 @@ export class SwitchSummonPhase extends SummonPhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (switchedPokemon) {
|
if (switchedPokemon) {
|
||||||
|
if (!this.scene.gameMode.isNuzlocke || this.doReturn)
|
||||||
party[this.slotIndex] = this.lastPokemon;
|
party[this.slotIndex] = this.lastPokemon;
|
||||||
|
else
|
||||||
|
party.splice(this.slotIndex, 1);
|
||||||
party[this.fieldIndex] = switchedPokemon;
|
party[this.fieldIndex] = switchedPokemon;
|
||||||
const showTextAndSummon = () => {
|
const showTextAndSummon = () => {
|
||||||
this.scene.ui.showText(this.player ?
|
this.scene.ui.showText(this.player ?
|
||||||
|
@ -3186,12 +3218,15 @@ export class FaintPhase extends PokemonPhase {
|
||||||
pokemon.addFriendship(-10);
|
pokemon.addFriendship(-10);
|
||||||
pokemon.hideInfo();
|
pokemon.hideInfo();
|
||||||
this.scene.playSound('faint');
|
this.scene.playSound('faint');
|
||||||
|
|
||||||
this.scene.tweens.add({
|
this.scene.tweens.add({
|
||||||
targets: pokemon,
|
targets: pokemon,
|
||||||
duration: 500,
|
duration: 500,
|
||||||
y: pokemon.y + 150,
|
y: pokemon.y + 150,
|
||||||
ease: 'Sine.easeIn',
|
ease: 'Sine.easeIn',
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
|
this.scene.faintCount++;
|
||||||
|
|
||||||
pokemon.setVisible(false);
|
pokemon.setVisible(false);
|
||||||
pokemon.y -= 150;
|
pokemon.y -= 150;
|
||||||
pokemon.trySetStatus(StatusEffect.FAINT);
|
pokemon.trySetStatus(StatusEffect.FAINT);
|
||||||
|
@ -3205,7 +3240,7 @@ export class FaintPhase extends PokemonPhase {
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, pokemon.isPlayer() && this.scene.gameMode.isNuzlocke);
|
||||||
}
|
}
|
||||||
|
|
||||||
tryOverrideForBattleSpec(): boolean {
|
tryOverrideForBattleSpec(): boolean {
|
||||||
|
@ -3238,6 +3273,7 @@ export class VictoryPhase extends PokemonPhase {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
this.scene.gameData.gameStats.pokemonDefeated++;
|
this.scene.gameData.gameStats.pokemonDefeated++;
|
||||||
|
this.scene.victoryCount++;
|
||||||
|
|
||||||
const participantIds = this.scene.currentBattle.playerParticipantIds;
|
const participantIds = this.scene.currentBattle.playerParticipantIds;
|
||||||
const party = this.scene.getParty();
|
const party = this.scene.getParty();
|
||||||
|
@ -3312,8 +3348,13 @@ export class VictoryPhase extends PokemonPhase {
|
||||||
|
|
||||||
if (!this.scene.getEnemyParty().find(p => this.scene.currentBattle.battleType ? !p?.isFainted(true) : p.isOnField())) {
|
if (!this.scene.getEnemyParty().find(p => this.scene.currentBattle.battleType ? !p?.isFainted(true) : p.isOnField())) {
|
||||||
this.scene.pushPhase(new BattleEndPhase(this.scene));
|
this.scene.pushPhase(new BattleEndPhase(this.scene));
|
||||||
if (this.scene.currentBattle.battleType === BattleType.TRAINER)
|
if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
|
||||||
|
if (this.scene.currentBattle.battleSpec === BattleSpec.NUZLOCKE_BOSS) {
|
||||||
|
this.scene.pushPhase(new NuzlockeBossSwitchPhase(this.scene));
|
||||||
|
return this.end();
|
||||||
|
}
|
||||||
this.scene.pushPhase(new TrainerVictoryPhase(this.scene));
|
this.scene.pushPhase(new TrainerVictoryPhase(this.scene));
|
||||||
|
}
|
||||||
if (this.scene.gameMode.isEndless || !this.scene.gameMode.isWaveFinal(this.scene.currentBattle.waveIndex)) {
|
if (this.scene.gameMode.isEndless || !this.scene.gameMode.isWaveFinal(this.scene.currentBattle.waveIndex)) {
|
||||||
this.scene.pushPhase(new EggLapsePhase(this.scene));
|
this.scene.pushPhase(new EggLapsePhase(this.scene));
|
||||||
if (this.scene.currentBattle.waveIndex % 10)
|
if (this.scene.currentBattle.waveIndex % 10)
|
||||||
|
@ -3550,6 +3591,8 @@ export class GameOverPhase extends BattlePhase {
|
||||||
|
|
||||||
handleUnlocks(): void {
|
handleUnlocks(): void {
|
||||||
if (this.victory && this.scene.gameMode.isClassic) {
|
if (this.victory && this.scene.gameMode.isClassic) {
|
||||||
|
if (!this.scene.gameData.unlocks[Unlockables.NUZLOCKE_MODE] && this.scene.victoryCount >= 250 && !this.scene.reviveCount)
|
||||||
|
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.NUZLOCKE_MODE));
|
||||||
if (!this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE])
|
if (!this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE])
|
||||||
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.ENDLESS_MODE));
|
this.scene.unshiftPhase(new UnlockPhase(this.scene, Unlockables.ENDLESS_MODE));
|
||||||
if (this.scene.getParty().filter(p => p.fusionSpecies).length && !this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE])
|
if (this.scene.getParty().filter(p => p.fusionSpecies).length && !this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE])
|
||||||
|
@ -4157,6 +4200,13 @@ export class AttemptCapturePhase extends PokemonPhase {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Promise.all([ pokemon.hideInfo(), this.scene.gameData.setPokemonCaught(pokemon) ]).then(() => {
|
Promise.all([ pokemon.hideInfo(), this.scene.gameData.setPokemonCaught(pokemon) ]).then(() => {
|
||||||
|
if (this.scene.gameMode.isNuzlocke && this.scene.currentBattle.waveIndex % 10 !== 1) {
|
||||||
|
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
|
||||||
|
removePokemon();
|
||||||
|
end();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.scene.getParty().length === 6) {
|
if (this.scene.getParty().length === 6) {
|
||||||
const promptRelease = () => {
|
const promptRelease = () => {
|
||||||
this.scene.ui.showText(`Your party is full.\nRelease a Pokémon to make room for ${pokemon.name}?`, null, () => {
|
this.scene.ui.showText(`Your party is full.\nRelease a Pokémon to make room for ${pokemon.name}?`, null, () => {
|
||||||
|
@ -4318,7 +4368,7 @@ export class SelectModifierPhase extends BattlePhase {
|
||||||
modifierType = typeOptions[cursor].type;
|
modifierType = typeOptions[cursor].type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1));
|
const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1), this.scene.gameMode);
|
||||||
const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT];
|
const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT];
|
||||||
modifierType = shopOption.type;
|
modifierType = shopOption.type;
|
||||||
cost = shopOption.cost;
|
cost = shopOption.cost;
|
||||||
|
@ -4556,6 +4606,65 @@ export class ScanIvsPhase extends PokemonPhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NuzlockeBossSwitchPhase extends BattlePhase {
|
||||||
|
start(): void {
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
this.scene.currentBattle.addBattleScore(this.scene);
|
||||||
|
|
||||||
|
this.scene.gameData.gameStats.trainersDefeated++;
|
||||||
|
|
||||||
|
this.scene.clearEnemyHeldItemModifiers();
|
||||||
|
|
||||||
|
const pokemon = this.scene.addEnemyPokemon(getPokemonSpecies(Species.NUZLEAF), 300, TrainerSlot.NONE, true);
|
||||||
|
pokemon.setAlpha(0);
|
||||||
|
pokemon.x += 16;
|
||||||
|
pokemon.y -= 16;
|
||||||
|
pokemon.setBoss(true, 5);
|
||||||
|
|
||||||
|
this.scene.currentBattle.battleType = BattleType.WILD;
|
||||||
|
this.scene.currentBattle.enemyParty = [ pokemon ];
|
||||||
|
|
||||||
|
pokemon.loadAssets().then(() => {
|
||||||
|
this.scene.add.existing(pokemon);
|
||||||
|
this.scene.field.add(pokemon);
|
||||||
|
|
||||||
|
this.scene.gameData.setPokemonSeen(pokemon, true, false);
|
||||||
|
|
||||||
|
const playerPokemon = this.scene.getPlayerPokemon() as Pokemon;
|
||||||
|
if (playerPokemon?.visible)
|
||||||
|
this.scene.field.moveBelow(pokemon, playerPokemon);
|
||||||
|
this.scene.currentBattle.seenEnemyPartyMemberIds.add(pokemon.id);
|
||||||
|
|
||||||
|
pokemon.initBattleInfo();
|
||||||
|
|
||||||
|
regenerateModifierPoolThresholds(this.scene.getEnemyField(), ModifierPoolType.WILD);
|
||||||
|
this.scene.generateEnemyModifiers();
|
||||||
|
|
||||||
|
this.scene.updateModifiers(false);
|
||||||
|
this.scene.updateFieldScale();
|
||||||
|
pokemon.showInfo();
|
||||||
|
pokemon.playAnim();
|
||||||
|
pokemon.setVisible(true);
|
||||||
|
pokemon.getSprite().setVisible(true);
|
||||||
|
this.scene.updateFieldScale();
|
||||||
|
this.scene.tweens.add({
|
||||||
|
targets: pokemon,
|
||||||
|
duration: 250,
|
||||||
|
ease: 'Sine.easeIn',
|
||||||
|
alpha: 1,
|
||||||
|
x: '-=16',
|
||||||
|
y: '+=16',
|
||||||
|
onComplete: () => {
|
||||||
|
pokemon.cry();
|
||||||
|
pokemon.resetSummonData();
|
||||||
|
this.scene.time.delayedCall(1000, () => this.end());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class TrainerMessageTestPhase extends BattlePhase {
|
export class TrainerMessageTestPhase extends BattlePhase {
|
||||||
private trainerTypes: TrainerType[];
|
private trainerTypes: TrainerType[];
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,9 @@ export interface SessionSaveData {
|
||||||
pokeballCounts: PokeballCounts;
|
pokeballCounts: PokeballCounts;
|
||||||
money: integer;
|
money: integer;
|
||||||
score: integer;
|
score: integer;
|
||||||
|
victoryCount: integer;
|
||||||
|
faintCount: integer;
|
||||||
|
reviveCount: integer;
|
||||||
waveIndex: integer;
|
waveIndex: integer;
|
||||||
battleType: BattleType;
|
battleType: BattleType;
|
||||||
trainer: TrainerData;
|
trainer: TrainerData;
|
||||||
|
@ -541,6 +544,9 @@ export class GameData {
|
||||||
pokeballCounts: scene.pokeballCounts,
|
pokeballCounts: scene.pokeballCounts,
|
||||||
money: scene.money,
|
money: scene.money,
|
||||||
score: scene.score,
|
score: scene.score,
|
||||||
|
victoryCount: scene.victoryCount,
|
||||||
|
faintCount: scene.faintCount,
|
||||||
|
reviveCount: scene.reviveCount,
|
||||||
waveIndex: scene.currentBattle.waveIndex,
|
waveIndex: scene.currentBattle.waveIndex,
|
||||||
battleType: scene.currentBattle.battleType,
|
battleType: scene.currentBattle.battleType,
|
||||||
trainer: scene.currentBattle.battleType == BattleType.TRAINER ? new TrainerData(scene.currentBattle.trainer) : null,
|
trainer: scene.currentBattle.battleType == BattleType.TRAINER ? new TrainerData(scene.currentBattle.trainer) : null,
|
||||||
|
|
|
@ -8,6 +8,8 @@ export class GameStats {
|
||||||
public sessionsWon: integer;
|
public sessionsWon: integer;
|
||||||
public dailyRunSessionsPlayed: integer;
|
public dailyRunSessionsPlayed: integer;
|
||||||
public dailyRunSessionsWon: integer;
|
public dailyRunSessionsWon: integer;
|
||||||
|
public nuzlockeSessionsPlayed: integer;
|
||||||
|
public nuzlockeSessionsWon: integer;
|
||||||
public endlessSessionsPlayed: integer;
|
public endlessSessionsPlayed: integer;
|
||||||
public highestEndlessWave: integer;
|
public highestEndlessWave: integer;
|
||||||
public highestLevel: integer;
|
public highestLevel: integer;
|
||||||
|
@ -45,6 +47,8 @@ export class GameStats {
|
||||||
this.sessionsWon = source?.sessionsWon || 0;
|
this.sessionsWon = source?.sessionsWon || 0;
|
||||||
this.dailyRunSessionsPlayed = source?.dailyRunSessionsPlayed || 0;
|
this.dailyRunSessionsPlayed = source?.dailyRunSessionsPlayed || 0;
|
||||||
this.dailyRunSessionsWon = source?.dailyRunSessionsWon || 0;
|
this.dailyRunSessionsWon = source?.dailyRunSessionsWon || 0;
|
||||||
|
this.nuzlockeSessionsPlayed = source?.nuzlockeSessionsPlayed || 0;
|
||||||
|
this.nuzlockeSessionsWon = source?.nuzlockeSessionsWon || 0;
|
||||||
this.endlessSessionsPlayed = source?.endlessSessionsPlayed || 0;
|
this.endlessSessionsPlayed = source?.endlessSessionsPlayed || 0;
|
||||||
this.highestEndlessWave = source?.highestEndlessWave || 0;
|
this.highestEndlessWave = source?.highestEndlessWave || 0;
|
||||||
this.highestLevel = source?.highestLevel || 0;
|
this.highestLevel = source?.highestLevel || 0;
|
||||||
|
|
|
@ -49,6 +49,7 @@ export default class PokemonData {
|
||||||
public fusionLuck: integer;
|
public fusionLuck: integer;
|
||||||
|
|
||||||
public boss: boolean;
|
public boss: boolean;
|
||||||
|
public bossSegments: integer;
|
||||||
|
|
||||||
public summonData: PokemonSummonData;
|
public summonData: PokemonSummonData;
|
||||||
|
|
||||||
|
@ -90,8 +91,10 @@ export default class PokemonData {
|
||||||
this.fusionGender = source.fusionGender;
|
this.fusionGender = source.fusionGender;
|
||||||
this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0);
|
this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0);
|
||||||
|
|
||||||
if (!forHistory)
|
if (!forHistory) {
|
||||||
this.boss = (source instanceof EnemyPokemon && !!source.bossSegments) || (!this.player && !!source.boss);
|
this.bossSegments = !this.player ? source?.bossSegments || 0 : 0;
|
||||||
|
this.boss = !!this.bossSegments || !!source?.boss;
|
||||||
|
}
|
||||||
|
|
||||||
if (sourcePokemon) {
|
if (sourcePokemon) {
|
||||||
this.moveset = sourcePokemon.moveset;
|
this.moveset = sourcePokemon.moveset;
|
||||||
|
|
|
@ -3,7 +3,9 @@ import { GameModes, gameModes } from "../game-mode";
|
||||||
export enum Unlockables {
|
export enum Unlockables {
|
||||||
ENDLESS_MODE,
|
ENDLESS_MODE,
|
||||||
MINI_BLACK_HOLE,
|
MINI_BLACK_HOLE,
|
||||||
SPLICED_ENDLESS_MODE
|
SPLICED_ENDLESS_MODE,
|
||||||
|
NUZLOCKE_MODE,
|
||||||
|
GAUNTLET_MODE
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUnlockableName(unlockable: Unlockables) {
|
export function getUnlockableName(unlockable: Unlockables) {
|
||||||
|
@ -14,5 +16,9 @@ export function getUnlockableName(unlockable: Unlockables) {
|
||||||
return 'Mini Black Hole';
|
return 'Mini Black Hole';
|
||||||
case Unlockables.SPLICED_ENDLESS_MODE:
|
case Unlockables.SPLICED_ENDLESS_MODE:
|
||||||
return `${gameModes[GameModes.SPLICED_ENDLESS].getName()} Mode`;
|
return `${gameModes[GameModes.SPLICED_ENDLESS].getName()} Mode`;
|
||||||
|
case Unlockables.NUZLOCKE_MODE:
|
||||||
|
return `${gameModes[GameModes.NUZLOCKE].getName()} Mode`;
|
||||||
|
case Unlockables.GAUNTLET_MODE:
|
||||||
|
return `${gameModes[GameModes.GAUNTLET].getName()} Mode`;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -55,9 +55,11 @@ const displayStats: DisplayStats = {
|
||||||
sessionsWon: 'Classic Wins',
|
sessionsWon: 'Classic Wins',
|
||||||
dailyRunSessionsPlayed: 'Daily Run Attempts',
|
dailyRunSessionsPlayed: 'Daily Run Attempts',
|
||||||
dailyRunSessionsWon: 'Daily Run Wins',
|
dailyRunSessionsWon: 'Daily Run Wins',
|
||||||
|
nuzlockeSessionsPlayed: 'Nuzlocke Attempts?',
|
||||||
|
nuzlockeSessionsWon: 'Nuzlocke Wins?',
|
||||||
endlessSessionsPlayed: 'Endless Runs?',
|
endlessSessionsPlayed: 'Endless Runs?',
|
||||||
highestEndlessWave: 'Highest Wave (Endless)?',
|
highestEndlessWave: 'Highest Wave (Endless)?',
|
||||||
highestMoney: 'Highest Money',
|
highestMoney: 'Most Money',
|
||||||
highestDamage: 'Highest Damage',
|
highestDamage: 'Highest Damage',
|
||||||
highestHeal: 'Highest HP Healed',
|
highestHeal: 'Highest HP Healed',
|
||||||
pokemonSeen: 'Pokémon Encountered',
|
pokemonSeen: 'Pokémon Encountered',
|
||||||
|
|
|
@ -108,7 +108,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||||
|
|
||||||
const typeOptions = args[1] as ModifierTypeOption[];
|
const typeOptions = args[1] as ModifierTypeOption[];
|
||||||
const shopTypeOptions = !this.scene.gameMode.hasNoShop
|
const shopTypeOptions = !this.scene.gameMode.hasNoShop
|
||||||
? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1))
|
? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1), this.scene.gameMode)
|
||||||
: [];
|
: [];
|
||||||
const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24;
|
const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24;
|
||||||
|
|
||||||
|
|
|
@ -476,6 +476,10 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||||
}
|
}
|
||||||
this.optionsCursorObj.setPosition(8 - this.optionsBg.displayWidth, -19 - (16 * ((this.options.length - 1) - this.optionsCursor)));
|
this.optionsCursorObj.setPosition(8 - this.optionsBg.displayWidth, -19 - (16 * ((this.options.length - 1) - this.optionsCursor)));
|
||||||
} else {
|
} else {
|
||||||
|
if (cursor < this.scene.currentBattle.getBattlerCount()) {
|
||||||
|
while (cursor < 6 && !this.partySlots[cursor].visible)
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
changed = this.cursor !== cursor;
|
changed = this.cursor !== cursor;
|
||||||
if (changed) {
|
if (changed) {
|
||||||
this.lastCursor = this.cursor;
|
this.lastCursor = this.cursor;
|
||||||
|
@ -973,6 +977,9 @@ class PartySlot extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
slotInfoContainer.add(slotTmLabel);
|
slotInfoContainer.add(slotTmLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((this.scene as BattleScene).gameMode.isNuzlocke && this.pokemon.isFainted())
|
||||||
|
this.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
select(): void {
|
select(): void {
|
||||||
|
|
Loading…
Reference in New Issue