Implemented Repels

pull/544/head
Sophie Kujo 2024-05-06 04:37:48 -04:00
parent 6011794732
commit a3b3691084
5 changed files with 174 additions and 164 deletions

View File

@ -1,2 +1,2 @@
VITE_BYPASS_LOGIN=1 VITE_BYPASS_LOGIN=1
VITE_BYPASS_TUTORIAL=0 VITE_BYPASS_TUTORIAL=1

38
package-lock.json generated
View File

@ -2565,33 +2565,6 @@
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true "dev": true
}, },
"node_modules/happy-dom": {
"version": "14.3.9",
"resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.3.9.tgz",
"integrity": "sha512-0kPQchwthekcYpYN8CvCiq+/z5bqFYDLbTxZ+yDLwT8AFRVJDFadShHRxp3VAZRy7a5isOZ1j/LzsU1dtAIZMQ==",
"dev": true,
"optional": true,
"peer": true,
"dependencies": {
"entities": "^4.5.0",
"webidl-conversions": "^7.0.0",
"whatwg-mimetype": "^3.0.0"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/happy-dom/node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"dev": true,
"optional": true,
"peer": true,
"engines": {
"node": ">=12"
}
},
"node_modules/has-flag": { "node_modules/has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -5802,17 +5775,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/whatwg-mimetype": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
"integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
"dev": true,
"optional": true,
"peer": true,
"engines": {
"node": ">=12"
}
},
"node_modules/whatwg-url": { "node_modules/whatwg-url": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",

View File

@ -4,7 +4,7 @@ import { NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePh
import Pokemon, { PlayerPokemon, EnemyPokemon } from './field/pokemon'; import Pokemon, { PlayerPokemon, EnemyPokemon } from './field/pokemon';
import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies, speciesStarters } from './data/pokemon-species'; import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies, speciesStarters } from './data/pokemon-species';
import * as Utils from './utils'; import * as Utils from './utils';
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier } from './modifier/modifier'; import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, DoubleBattleChancePreventerModifier } from './modifier/modifier';
import { PokeballType } from './data/pokeball'; import { PokeballType } from './data/pokeball';
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from './data/battle-anims'; import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from './data/battle-anims';
import { Phase } from './phase'; import { Phase } from './phase';
@ -124,7 +124,7 @@ export default class BattleScene extends SceneBase {
public gamepadSupport: boolean = true; public gamepadSupport: boolean = true;
public enableTouchControls: boolean = false; public enableTouchControls: boolean = false;
public enableVibration: boolean = false; public enableVibration: boolean = false;
public disableMenu: boolean = false; public disableMenu: boolean = false;
public gameData: GameData; public gameData: GameData;
@ -189,14 +189,14 @@ export default class BattleScene extends SceneBase {
private bgmResumeTimer: Phaser.Time.TimerEvent; private bgmResumeTimer: Phaser.Time.TimerEvent;
private bgmCache: Set<string> = new Set(); private bgmCache: Set<string> = new Set();
private playTimeTimer: Phaser.Time.TimerEvent; private playTimeTimer: Phaser.Time.TimerEvent;
private buttonKeys: Phaser.Input.Keyboard.Key[][]; private buttonKeys: Phaser.Input.Keyboard.Key[][];
private lastProcessedButtonPressTimes: Map<Button, number> = new Map(); private lastProcessedButtonPressTimes: Map<Button, number> = new Map();
// movementButtonLock ensures only a single movement key is firing repeated inputs // movementButtonLock ensures only a single movement key is firing repeated inputs
// (i.e. by holding down a button) at a time // (i.e. by holding down a button) at a time
private movementButtonLock: Button; private movementButtonLock: Button;
// using a dualshock controller as a map // using a dualshock controller as a map
private gamepadKeyConfig = { private gamepadKeyConfig = {
[Button.UP]: 12, // up [Button.UP]: 12, // up
[Button.DOWN]: 13, // down [Button.DOWN]: 13, // down
@ -228,7 +228,7 @@ export default class BattleScene extends SceneBase {
initSpecies(); initSpecies();
initMoves(); initMoves();
initAbilities(); initAbilities();
this.phaseQueue = []; this.phaseQueue = [];
this.phaseQueuePrepend = []; this.phaseQueuePrepend = [];
this.phaseQueuePrependSpliceIndex = -1; this.phaseQueuePrependSpliceIndex = -1;
@ -243,7 +243,7 @@ export default class BattleScene extends SceneBase {
experimental = this.hasExpSprite(key); experimental = this.hasExpSprite(key);
if (variant) if (variant)
atlasPath = atlasPath.replace('variant/', ''); atlasPath = atlasPath.replace('variant/', '');
this.load.atlas(key, `images/pokemon/${variant ? 'variant/' : ''}${experimental ? 'exp/' : ''}${atlasPath}.png`, `images/pokemon/${variant ? 'variant/' : ''}${experimental ? 'exp/' : ''}${atlasPath}.json`); this.load.atlas(key, `images/pokemon/${variant ? 'variant/' : ''}${experimental ? 'exp/' : ''}${atlasPath}.png`, `images/pokemon/${variant ? 'variant/' : ''}${experimental ? 'exp/' : ''}${atlasPath}.json`);
} }
async preload() { async preload() {
@ -251,8 +251,8 @@ export default class BattleScene extends SceneBase {
const scene = this; const scene = this;
const originalRealInRange = Phaser.Math.RND.realInRange; const originalRealInRange = Phaser.Math.RND.realInRange;
Phaser.Math.RND.realInRange = function (min: number, max: number): number { Phaser.Math.RND.realInRange = function (min: number, max: number): number {
const ret = originalRealInRange.apply(this, [ min, max ]); const ret = originalRealInRange.apply(this, [min, max]);
const args = [ 'RNG', ++scene.rngCounter, ret / (max - min), `min: ${min} / max: ${max}` ]; const args = ['RNG', ++scene.rngCounter, ret / (max - min), `min: ${min} / max: ${max}`];
args.push(`seed: ${scene.rngSeedOverride || scene.waveSeed || scene.seed}`); args.push(`seed: ${scene.rngSeedOverride || scene.waveSeed || scene.seed}`);
if (scene.rngOffset) if (scene.rngOffset)
args.push(`offset: ${scene.rngOffset}`); args.push(`offset: ${scene.rngOffset}`);
@ -260,7 +260,7 @@ export default class BattleScene extends SceneBase {
return ret; return ret;
}; };
} }
populateAnims(); populateAnims();
await this.initVariantData(); await this.initVariantData();
@ -295,7 +295,7 @@ export default class BattleScene extends SceneBase {
this.arenaBg = this.add.sprite(0, 0, 'plains_bg'); this.arenaBg = this.add.sprite(0, 0, 'plains_bg');
this.arenaBgTransition = this.add.sprite(0, 0, 'plains_bg'); this.arenaBgTransition = this.add.sprite(0, 0, 'plains_bg');
[ this.arenaBgTransition, this.arenaBg ].forEach(a => { [this.arenaBgTransition, this.arenaBg].forEach(a => {
a.setPipeline(this.fieldSpritePipeline); a.setPipeline(this.fieldSpritePipeline);
a.setScale(6); a.setScale(6);
a.setOrigin(0); a.setOrigin(0);
@ -427,7 +427,7 @@ export default class BattleScene extends SceneBase {
this.arenaPlayerTransition.setVisible(false); this.arenaPlayerTransition.setVisible(false);
this.arenaNextEnemy.setVisible(false); this.arenaNextEnemy.setVisible(false);
[ this.arenaPlayer, this.arenaPlayerTransition, this.arenaEnemy, this.arenaNextEnemy ].forEach(a => { [this.arenaPlayer, this.arenaPlayerTransition, this.arenaEnemy, this.arenaNextEnemy].forEach(a => {
if (a instanceof Phaser.GameObjects.Sprite) if (a instanceof Phaser.GameObjects.Sprite)
a.setOrigin(0, 0); a.setOrigin(0, 0);
field.add(a); field.add(a);
@ -466,12 +466,12 @@ export default class BattleScene extends SceneBase {
ui.setup(); ui.setup();
const defaultMoves = [ Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE ]; const defaultMoves = [Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE];
Promise.all([ Promise.all([
Promise.all(loadPokemonAssets), Promise.all(loadPokemonAssets),
initCommonAnims(this).then(() => loadCommonAnimAssets(this, true)), initCommonAnims(this).then(() => loadCommonAnimAssets(this, true)),
Promise.all([ Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE ].map(m => initMoveAnim(this, m))).then(() => loadMoveAnimAssets(this, defaultMoves, true)), Promise.all([Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE].map(m => initMoveAnim(this, m))).then(() => loadMoveAnimAssets(this, defaultMoves, true)),
this.initStarterColors() this.initStarterColors()
]).then(() => { ]).then(() => {
this.pushPhase(new LoginPhase(this)); this.pushPhase(new LoginPhase(this));
@ -491,7 +491,7 @@ export default class BattleScene extends SceneBase {
this.playTimeTimer = this.time.addEvent({ this.playTimeTimer = this.time.addEvent({
delay: Utils.fixedInt(1000), delay: Utils.fixedInt(1000),
repeat: -1, repeat: -1,
callback: () => { callback: () => {
if (this.gameData) if (this.gameData)
this.gameData.gameStats.playTime++; this.gameData.gameStats.playTime++;
if (this.sessionPlayTime !== null) if (this.sessionPlayTime !== null)
@ -529,14 +529,14 @@ export default class BattleScene extends SceneBase {
variantTree = variantTree[k]; variantTree = variantTree[k];
expTree = expTree[k]; expTree = expTree[k];
} else if (variantTree.hasOwnProperty(k) && expTree.hasOwnProperty(k)) { } else if (variantTree.hasOwnProperty(k) && expTree.hasOwnProperty(k)) {
if ([ 'back', 'female' ].includes(k)) if (['back', 'female'].includes(k))
traverseVariantData(keys.concat(k)); traverseVariantData(keys.concat(k));
else else
variantTree[k] = expTree[k]; variantTree[k] = expTree[k];
} }
}); });
}; };
Object.keys(expVariantData).forEach(ek => traverseVariantData([ ek ])); Object.keys(expVariantData).forEach(ek => traverseVariantData([ek]));
} }
Promise.resolve(); Promise.resolve();
}); });
@ -710,9 +710,9 @@ export default class BattleScene extends SceneBase {
addPokemonIcon(pokemon: Pokemon, x: number, y: number, originX: number = 0.5, originY: number = 0.5, ignoreOverride: boolean = false): Phaser.GameObjects.Container { addPokemonIcon(pokemon: Pokemon, x: number, y: number, originX: number = 0.5, originY: number = 0.5, ignoreOverride: boolean = false): Phaser.GameObjects.Container {
const container = this.add.container(x, y); const container = this.add.container(x, y);
const icon = this.add.sprite(0, 0, pokemon.getIconAtlasKey(ignoreOverride)); const icon = this.add.sprite(0, 0, pokemon.getIconAtlasKey(ignoreOverride));
icon.setFrame(pokemon.getIconId(true)); icon.setFrame(pokemon.getIconId(true));
icon.setOrigin(0.5, 0); icon.setOrigin(0.5, 0);
container.add(icon); container.add(icon);
@ -727,7 +727,7 @@ export default class BattleScene extends SceneBase {
const originalFrame = icon.frame; const originalFrame = icon.frame;
const iconHeight = (icon.frame.cutHeight <= fusionIcon.frame.cutHeight ? Math.ceil : Math.floor)((icon.frame.cutHeight + fusionIcon.frame.cutHeight) / 4); const iconHeight = (icon.frame.cutHeight <= fusionIcon.frame.cutHeight ? Math.ceil : Math.floor)((icon.frame.cutHeight + fusionIcon.frame.cutHeight) / 4);
// Inefficient, but for some reason didn't work with only the unique properties as part of the name // Inefficient, but for some reason didn't work with only the unique properties as part of the name
const iconFrameId = `${icon.frame.name}f${fusionIcon.frame.name}`; const iconFrameId = `${icon.frame.name}f${fusionIcon.frame.name}`;
@ -785,7 +785,7 @@ export default class BattleScene extends SceneBase {
this.gameData = new GameData(this); this.gameData = new GameData(this);
this.gameMode = gameModes[GameModes.CLASSIC]; this.gameMode = gameModes[GameModes.CLASSIC];
this.setSeed(SEED_OVERRIDE || Utils.randomString(24)); this.setSeed(SEED_OVERRIDE || Utils.randomString(24));
console.log('Seed:', this.seed); console.log('Seed:', this.seed);
@ -796,7 +796,7 @@ export default class BattleScene extends SceneBase {
this.lockModifierTiers = false; this.lockModifierTiers = false;
this.pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ])); this.pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [t, 0]));
this.pokeballCounts[PokeballType.POKEBALL] += 5; this.pokeballCounts[PokeballType.POKEBALL] += 5;
this.modifiers = []; this.modifiers = [];
@ -809,7 +809,7 @@ export default class BattleScene extends SceneBase {
this.party = []; this.party = [];
for (let p of this.getEnemyParty()) for (let p of this.getEnemyParty())
p.destroy(); p.destroy();
this.currentBattle = null; this.currentBattle = null;
this.waveCountText.setText(startingWave.toString()); this.waveCountText.setText(startingWave.toString());
@ -821,14 +821,14 @@ export default class BattleScene extends SceneBase {
this.updateScoreText(); this.updateScoreText();
this.scoreText.setVisible(false); this.scoreText.setVisible(false);
[ this.luckLabelText, this.luckText ].map(t => t.setVisible(false)); [this.luckLabelText, this.luckText].map(t => t.setVisible(false));
this.newArena(STARTING_BIOME_OVERRIDE || Biome.TOWN); this.newArena(STARTING_BIOME_OVERRIDE || Biome.TOWN);
this.arenaBgTransition.setPosition(0, 0); this.arenaBgTransition.setPosition(0, 0);
this.arenaPlayer.setPosition(300, 0); this.arenaPlayer.setPosition(300, 0);
this.arenaPlayerTransition.setPosition(0, 0); this.arenaPlayerTransition.setPosition(0, 0);
[ this.arenaEnemy, this.arenaNextEnemy ].forEach(a => a.setPosition(-280, 0)); [this.arenaEnemy, this.arenaNextEnemy].forEach(a => a.setPosition(-280, 0));
this.arenaNextEnemy.setVisible(false); this.arenaNextEnemy.setVisible(false);
this.arena.init(); this.arena.init();
@ -854,7 +854,7 @@ export default class BattleScene extends SceneBase {
this.fadeOutBgm(250, false); this.fadeOutBgm(250, false);
this.tweens.add({ this.tweens.add({
targets: [ this.uiContainer ], targets: [this.uiContainer],
alpha: 0, alpha: 0,
duration: 250, duration: 250,
ease: 'Sine.easeInOut', ease: 'Sine.easeInOut',
@ -870,6 +870,9 @@ export default class BattleScene extends SceneBase {
} }
newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle { newBattle(waveIndex?: integer, battleType?: BattleType, trainerData?: TrainerData, double?: boolean): Battle {
if (this.getModifiers(DoubleBattleChancePreventerModifier) != null) {
double = false;
}
let newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1); let newWaveIndex = waveIndex || ((this.currentBattle?.waveIndex || (startingWave - 1)) + 1);
let newDouble: boolean; let newDouble: boolean;
let newBattleType: BattleType; let newBattleType: BattleType;
@ -880,7 +883,7 @@ export default class BattleScene extends SceneBase {
this.resetSeed(newWaveIndex); this.resetSeed(newWaveIndex);
const playerField = this.getPlayerField(); const playerField = this.getPlayerField();
if (this.gameMode.hasFixedBattles && fixedBattles.hasOwnProperty(newWaveIndex) && trainerData === undefined) { if (this.gameMode.hasFixedBattles && fixedBattles.hasOwnProperty(newWaveIndex) && trainerData === undefined) {
battleConfig = fixedBattles[newWaveIndex]; battleConfig = fixedBattles[newWaveIndex];
newDouble = battleConfig.double; newDouble = battleConfig.double;
@ -988,7 +991,7 @@ export default class BattleScene extends SceneBase {
this.pushPhase(new LevelCapPhase(this)); this.pushPhase(new LevelCapPhase(this));
} }
} }
return this.currentBattle; return this.currentBattle;
} }
@ -1070,7 +1073,7 @@ export default class BattleScene extends SceneBase {
case Species.OINKOLOGNE: case Species.OINKOLOGNE:
return gender === Gender.FEMALE ? 1 : 0; return gender === Gender.FEMALE ? 1 : 0;
case Species.TOXTRICITY: case Species.TOXTRICITY:
const lowkeyNatures = [ Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL ]; const lowkeyNatures = [Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL];
if (nature !== undefined && lowkeyNatures.indexOf(nature) > -1) if (nature !== undefined && lowkeyNatures.indexOf(nature) > -1)
return 1; return 1;
return 0; return 0;
@ -1147,7 +1150,7 @@ export default class BattleScene extends SceneBase {
party.forEach((pokemon, p) => { party.forEach((pokemon, p) => {
if (!pokemon.pokerus || infectedIndexes.indexOf(p) > -1) if (!pokemon.pokerus || infectedIndexes.indexOf(p) > -1)
return; return;
this.executeWithSeedOffset(() => { this.executeWithSeedOffset(() => {
if (p) if (p)
spread(p, -1); spread(p, -1);
@ -1160,7 +1163,7 @@ export default class BattleScene extends SceneBase {
resetSeed(waveIndex?: integer): void { resetSeed(waveIndex?: integer): void {
const wave = waveIndex || this.currentBattle?.waveIndex || 0; const wave = waveIndex || this.currentBattle?.waveIndex || 0;
this.waveSeed = Utils.shiftCharCodes(this.seed, wave); this.waveSeed = Utils.shiftCharCodes(this.seed, wave);
Phaser.Math.RND.sow([ this.waveSeed ]); Phaser.Math.RND.sow([this.waveSeed]);
console.log('Wave Seed:', this.waveSeed, wave); console.log('Wave Seed:', this.waveSeed, wave);
this.rngCounter = 0; this.rngCounter = 0;
} }
@ -1172,7 +1175,7 @@ export default class BattleScene extends SceneBase {
const tempRngOffset = this.rngOffset; const tempRngOffset = this.rngOffset;
const tempRngSeedOverride = this.rngSeedOverride; const tempRngSeedOverride = this.rngSeedOverride;
const state = Phaser.Math.RND.state(); const state = Phaser.Math.RND.state();
Phaser.Math.RND.sow([ Utils.shiftCharCodes(seedOverride || this.seed, offset) ]); Phaser.Math.RND.sow([Utils.shiftCharCodes(seedOverride || this.seed, offset)]);
this.rngCounter = 0; this.rngCounter = 0;
this.rngOffset = offset; this.rngOffset = offset;
this.rngSeedOverride = seedOverride || ''; this.rngSeedOverride = seedOverride || '';
@ -1199,7 +1202,7 @@ export default class BattleScene extends SceneBase {
} }
initPokemonSprite(sprite: Phaser.GameObjects.Sprite, pokemon?: Pokemon, hasShadow: boolean = false, ignoreOverride: boolean = false): Phaser.GameObjects.Sprite { initPokemonSprite(sprite: Phaser.GameObjects.Sprite, pokemon?: Pokemon, hasShadow: boolean = false, ignoreOverride: boolean = false): Phaser.GameObjects.Sprite {
sprite.setPipeline(this.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: hasShadow, ignoreOverride: ignoreOverride, teraColor: pokemon ? getTypeRgb(pokemon.getTeraType()) : undefined }); sprite.setPipeline(this.spritePipeline, { tone: [0.0, 0.0, 0.0, 0.0], hasShadow: hasShadow, ignoreOverride: ignoreOverride, teraColor: pokemon ? getTypeRgb(pokemon.getTeraType()) : undefined });
this.spriteSparkleHandler.add(sprite); this.spriteSparkleHandler.add(sprite);
return sprite; return sprite;
} }
@ -1247,7 +1250,7 @@ export default class BattleScene extends SceneBase {
} }
updateAndShowLuckText(duration: integer): void { updateAndShowLuckText(duration: integer): void {
const labels = [ this.luckLabelText, this.luckText ]; const labels = [this.luckLabelText, this.luckText];
labels.map(t => { labels.map(t => {
t.setAlpha(0); t.setAlpha(0);
t.setVisible(true); t.setVisible(true);
@ -1267,7 +1270,7 @@ export default class BattleScene extends SceneBase {
} }
hideLuckText(duration: integer): void { hideLuckText(duration: integer): void {
const labels = [ this.luckLabelText, this.luckText ]; const labels = [this.luckLabelText, this.luckText];
this.tweens.add({ this.tweens.add({
targets: labels, targets: labels,
duration: duration, duration: duration,
@ -1283,7 +1286,7 @@ export default class BattleScene extends SceneBase {
this.waveCountText.setY(-(this.game.canvas.height / 6) + (enemyModifierCount ? enemyModifierCount <= 12 ? 15 : 24 : 0)); this.waveCountText.setY(-(this.game.canvas.height / 6) + (enemyModifierCount ? enemyModifierCount <= 12 ? 15 : 24 : 0));
this.moneyText.setY(this.waveCountText.y + 10); this.moneyText.setY(this.waveCountText.y + 10);
this.scoreText.setY(this.moneyText.y + 10); this.scoreText.setY(this.moneyText.y + 10);
[ this.luckLabelText, this.luckText ].map(l => l.setY((this.scoreText.visible ? this.scoreText : this.moneyText).y + 10)); [this.luckLabelText, this.luckText].map(l => l.setY((this.scoreText.visible ? this.scoreText : this.moneyText).y + 10));
const offsetY = (this.scoreText.visible ? this.scoreText : this.moneyText).y + 15; const offsetY = (this.scoreText.visible ? this.scoreText : this.moneyText).y + 15;
this.partyExpBar.setY(offsetY); this.partyExpBar.setY(offsetY);
this.candyBar.setY(offsetY + 15); this.candyBar.setY(offsetY + 15);
@ -1368,7 +1371,7 @@ export default class BattleScene extends SceneBase {
} else if (this.buttonJustPressed(Button.ACTION) || this.repeatInputDurationJustPassed(Button.ACTION)) { } else if (this.buttonJustPressed(Button.ACTION) || this.repeatInputDurationJustPassed(Button.ACTION)) {
inputSuccess = this.ui.processInput(Button.ACTION); inputSuccess = this.ui.processInput(Button.ACTION);
this.setLastProcessedMovementTime(Button.ACTION); this.setLastProcessedMovementTime(Button.ACTION);
} else if (this.buttonJustPressed(Button.CANCEL)|| this.repeatInputDurationJustPassed(Button.CANCEL)) { } else if (this.buttonJustPressed(Button.CANCEL) || this.repeatInputDurationJustPassed(Button.CANCEL)) {
inputSuccess = this.ui.processInput(Button.CANCEL); inputSuccess = this.ui.processInput(Button.CANCEL);
this.setLastProcessedMovementTime(Button.CANCEL); this.setLastProcessedMovementTime(Button.CANCEL);
} else if (this.buttonJustPressed(Button.MENU)) { } else if (this.buttonJustPressed(Button.MENU)) {
@ -1405,25 +1408,25 @@ export default class BattleScene extends SceneBase {
} else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) { } else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
if (this.buttonJustPressed(Button.CYCLE_SHINY)) { if (this.buttonJustPressed(Button.CYCLE_SHINY)) {
inputSuccess = this.ui.processInput(Button.CYCLE_SHINY); inputSuccess = this.ui.processInput(Button.CYCLE_SHINY);
this.setLastProcessedMovementTime(Button.CYCLE_SHINY); this.setLastProcessedMovementTime(Button.CYCLE_SHINY);
} else if (this.buttonJustPressed(Button.CYCLE_FORM)) { } else if (this.buttonJustPressed(Button.CYCLE_FORM)) {
inputSuccess = this.ui.processInput(Button.CYCLE_FORM); inputSuccess = this.ui.processInput(Button.CYCLE_FORM);
this.setLastProcessedMovementTime(Button.CYCLE_FORM); this.setLastProcessedMovementTime(Button.CYCLE_FORM);
} else if (this.buttonJustPressed(Button.CYCLE_GENDER)) { } else if (this.buttonJustPressed(Button.CYCLE_GENDER)) {
inputSuccess = this.ui.processInput(Button.CYCLE_GENDER); inputSuccess = this.ui.processInput(Button.CYCLE_GENDER);
this.setLastProcessedMovementTime(Button.CYCLE_GENDER); this.setLastProcessedMovementTime(Button.CYCLE_GENDER);
} else if (this.buttonJustPressed(Button.CYCLE_ABILITY)) { } else if (this.buttonJustPressed(Button.CYCLE_ABILITY)) {
inputSuccess = this.ui.processInput(Button.CYCLE_ABILITY); inputSuccess = this.ui.processInput(Button.CYCLE_ABILITY);
this.setLastProcessedMovementTime(Button.CYCLE_ABILITY); this.setLastProcessedMovementTime(Button.CYCLE_ABILITY);
} else if (this.buttonJustPressed(Button.CYCLE_NATURE)) { } else if (this.buttonJustPressed(Button.CYCLE_NATURE)) {
inputSuccess = this.ui.processInput(Button.CYCLE_NATURE); inputSuccess = this.ui.processInput(Button.CYCLE_NATURE);
this.setLastProcessedMovementTime(Button.CYCLE_NATURE); this.setLastProcessedMovementTime(Button.CYCLE_NATURE);
} else if (this.buttonJustPressed(Button.CYCLE_VARIANT)) { } else if (this.buttonJustPressed(Button.CYCLE_VARIANT)) {
inputSuccess = this.ui.processInput(Button.CYCLE_VARIANT); inputSuccess = this.ui.processInput(Button.CYCLE_VARIANT);
this.setLastProcessedMovementTime(Button.CYCLE_VARIANT); this.setLastProcessedMovementTime(Button.CYCLE_VARIANT);
} else } else
return; return;
} else if (this.buttonJustPressed(Button.SPEED_UP)) { } else if (this.buttonJustPressed(Button.SPEED_UP)) {
if (this.gameSpeed < 5) { if (this.gameSpeed < 5) {
this.gameData.saveSetting(Setting.Game_Speed, settingOptions[Setting.Game_Speed].indexOf(`${this.gameSpeed}x`) + 1); this.gameData.saveSetting(Setting.Game_Speed, settingOptions[Setting.Game_Speed].indexOf(`${this.gameSpeed}x`) + 1);
if (this.ui?.getMode() === Mode.SETTINGS) if (this.ui?.getMode() === Mode.SETTINGS)
@ -1446,14 +1449,14 @@ export default class BattleScene extends SceneBase {
return; return;
} }
if (inputSuccess && this.enableVibration && typeof navigator.vibrate !== 'undefined') if (inputSuccess && this.enableVibration && typeof navigator.vibrate !== 'undefined')
navigator.vibrate(vibrationLength || 10); navigator.vibrate(vibrationLength || 10);
} }
/** /**
* gamepadButtonJustDown returns true if @param button has just been pressed down * gamepadButtonJustDown returns true if @param button has just been pressed down
* or not. It will only return true once, until the key is released and pressed down * or not. It will only return true once, until the key is released and pressed down
* again. * again.
*/ */
gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button): boolean { gamepadButtonJustDown(button: Phaser.Input.Gamepad.Button): boolean {
if (!button || !this.gamepadSupport) if (!button || !this.gamepadSupport)
return false; return false;
@ -1467,7 +1470,7 @@ export default class BattleScene extends SceneBase {
this.gamepadButtonStates[button.index] = false; this.gamepadButtonStates[button.index] = false;
return ret; return ret;
} }
buttonJustPressed(button: Button): boolean { buttonJustPressed(button: Button): boolean {
const gamepad = this.input.gamepad?.gamepads[0]; const gamepad = this.input.gamepad?.gamepads[0];
@ -1484,7 +1487,7 @@ export default class BattleScene extends SceneBase {
return false; return false;
return !this.gamepadButtonStates[button.index]; return !this.gamepadButtonStates[button.index];
} }
buttonJustReleased(button: Button): boolean { buttonJustReleased(button: Button): boolean {
const gamepad = this.input.gamepad?.gamepads[0]; const gamepad = this.input.gamepad?.gamepads[0];
@ -1596,7 +1599,7 @@ export default class BattleScene extends SceneBase {
fadeOutBgm(duration: integer = 500, destroy: boolean = true): boolean { fadeOutBgm(duration: integer = 500, destroy: boolean = true): boolean {
if (!this.bgm) if (!this.bgm)
return false; return false;
const bgm = this.sound.getAllPlaying().find(bgm => bgm.key === this.bgm.key); const bgm = this.sound.getAllPlaying().find(bgm => bgm.key === this.bgm.key);
if (bgm) { if (bgm) {
SoundFade.fadeOut(this, this.bgm, duration, destroy); SoundFade.fadeOut(this, this.bgm, duration, destroy);
return true; return true;
@ -1753,7 +1756,7 @@ export default class BattleScene extends SceneBase {
this.currentPhase = this.phaseQueue.shift(); this.currentPhase = this.phaseQueue.shift();
this.currentPhase.start(); this.currentPhase.start();
} }
overridePhase(phase: Phase): boolean { overridePhase(phase: Phase): boolean {
if (this.standbyPhase) if (this.standbyPhase)
return false; return false;
@ -1838,7 +1841,7 @@ export default class BattleScene extends SceneBase {
modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId))); modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId)));
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) { if ((modifier as PersistentModifier).add(this.modifiers, !!virtual, this)) {
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier)
success = modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]); success = modifier.apply([this.getPokemonById(modifier.pokemonId), true]);
if (playSound && !this.sound.get(soundName)) if (playSound && !this.sound.get(soundName))
this.playSound(soundName); this.playSound(soundName);
} else if (!virtual) { } else if (!virtual) {
@ -1846,7 +1849,7 @@ export default class BattleScene extends SceneBase {
this.queueMessage(`The stack for this item is full.\n You will receive ${defaultModifierType.name} instead.`, null, true); this.queueMessage(`The stack for this item is full.\n You will receive ${defaultModifierType.name} instead.`, null, true);
return this.addModifier(defaultModifierType.newModifier(), ignoreUpdate, playSound, false, instant).then(success => resolve(success)); return this.addModifier(defaultModifierType.newModifier(), ignoreUpdate, playSound, false, instant).then(success => resolve(success));
} }
for (let rm of modifiersToRemove) for (let rm of modifiersToRemove)
this.removeModifier(rm); this.removeModifier(rm);
@ -1860,7 +1863,7 @@ export default class BattleScene extends SceneBase {
for (let p in this.party) { for (let p in this.party) {
const pokemon = this.party[p]; const pokemon = this.party[p];
const args: any[] = [ pokemon ]; const args: any[] = [pokemon];
if (modifier instanceof PokemonHpRestoreModifier) { if (modifier instanceof PokemonHpRestoreModifier) {
if (!(modifier as PokemonHpRestoreModifier).fainted) { if (!(modifier as PokemonHpRestoreModifier).fainted) {
const hpRestoreMultiplier = new Utils.IntegerHolder(1); const hpRestoreMultiplier = new Utils.IntegerHolder(1);
@ -1870,7 +1873,7 @@ export default class BattleScene extends SceneBase {
args.push(1); args.push(1);
} else if (modifier instanceof FusePokemonModifier) } else if (modifier instanceof FusePokemonModifier)
args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon); args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon);
if (modifier.shouldApply(args)) { if (modifier.shouldApply(args)) {
const result = modifier.apply(args); const result = modifier.apply(args);
if (result instanceof Promise) if (result instanceof Promise)
@ -1879,10 +1882,10 @@ export default class BattleScene extends SceneBase {
success ||= result; success ||= result;
} }
} }
return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success)); return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success));
} else { } else {
const args = [ this ]; const args = [this];
if (modifier.shouldApply(args)) { if (modifier.shouldApply(args)) {
const result = modifier.apply(args); const result = modifier.apply(args);
if (result instanceof Promise) { if (result instanceof Promise) {
@ -1901,10 +1904,10 @@ export default class BattleScene extends SceneBase {
return new Promise(resolve => { return new Promise(resolve => {
const modifiersToRemove: PersistentModifier[] = []; const modifiersToRemove: PersistentModifier[] = [];
if (modifier instanceof TerastallizeModifier) if (modifier instanceof TerastallizeModifier)
modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId, false))); modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId, false)));
if ((modifier as PersistentModifier).add(this.enemyModifiers, false, this)) { if ((modifier as PersistentModifier).add(this.enemyModifiers, false, this)) {
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier)
modifier.apply([ this.getPokemonById(modifier.pokemonId), true ]); modifier.apply([this.getPokemonById(modifier.pokemonId), true]);
for (let rm of modifiersToRemove) for (let rm of modifiersToRemove)
this.removeModifier(rm, true); this.removeModifier(rm, true);
} }
@ -2006,7 +2009,7 @@ export default class BattleScene extends SceneBase {
} }
if (isBoss) if (isBoss)
count = Math.max(count, Math.floor(chances / 2)); count = Math.max(count, Math.floor(chances / 2));
getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance) getEnemyModifierTypesForWave(difficultyWaveIndex, count, [enemyPokemon], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance)
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this)); .map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this));
}); });
@ -2022,7 +2025,7 @@ export default class BattleScene extends SceneBase {
} }
setModifiersVisible(visible: boolean) { setModifiersVisible(visible: boolean) {
[ this.modifierBar, this.enemyModifierBar ].map(m => m.setVisible(visible)); [this.modifierBar, this.enemyModifierBar].map(m => m.setVisible(visible));
} }
updateModifiers(player?: boolean, instant?: boolean): Promise<void> { updateModifiers(player?: boolean, instant?: boolean): Promise<void> {
@ -2071,7 +2074,7 @@ export default class BattleScene extends SceneBase {
if (modifierIndex > -1) { if (modifierIndex > -1) {
modifiers.splice(modifierIndex, 1); modifiers.splice(modifierIndex, 1);
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier)
modifier.apply([ this.getPokemonById(modifier.pokemonId), false ]); modifier.apply([this.getPokemonById(modifier.pokemonId), false]);
return true; return true;
} }

View File

@ -73,16 +73,16 @@ export class ModifierType {
let poolTypes: ModifierPoolType[]; let poolTypes: ModifierPoolType[];
switch (poolType) { switch (poolType) {
case ModifierPoolType.PLAYER: case ModifierPoolType.PLAYER:
poolTypes = [ poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD ]; poolTypes = [poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD];
break; break;
case ModifierPoolType.WILD: case ModifierPoolType.WILD:
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER ]; poolTypes = [poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER];
break; break;
case ModifierPoolType.TRAINER: case ModifierPoolType.TRAINER:
poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD ]; poolTypes = [poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD];
break; break;
default: default:
poolTypes = [ poolType ]; poolTypes = [poolType];
break; break;
} }
// Try multiple pool types in case of stolen items // Try multiple pool types in case of stolen items
@ -111,7 +111,7 @@ export class ModifierType {
type ModifierTypeGeneratorFunc = (party: Pokemon[], pregenArgs?: any[]) => ModifierType; type ModifierTypeGeneratorFunc = (party: Pokemon[], pregenArgs?: any[]) => ModifierType;
export class ModifierTypeGenerator extends ModifierType { export class ModifierTypeGenerator extends ModifierType {
private genTypeFunc: ModifierTypeGeneratorFunc; private genTypeFunc: ModifierTypeGeneratorFunc;
constructor(genTypeFunc: ModifierTypeGeneratorFunc) { constructor(genTypeFunc: ModifierTypeGeneratorFunc) {
super(null, null, null, null); super(null, null, null, null);
@ -193,11 +193,11 @@ export class PokemonHpRestoreModifierType extends PokemonModifierType {
constructor(name: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string, group?: string) { constructor(name: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string, group?: string) {
super(name, restorePoints ? `Restores ${restorePoints} HP or ${restorePercent}% HP for one Pokémon, whichever is higher` : `Fully restores HP for one Pokémon${healStatus ? ' and heals any status ailment' : ''}`, super(name, restorePoints ? `Restores ${restorePoints} HP or ${restorePercent}% HP for one Pokémon, whichever is higher` : `Fully restores HP for one Pokémon${healStatus ? ' and heals any status ailment' : ''}`,
newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)), newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)),
selectFilter || ((pokemon: PlayerPokemon) => { selectFilter || ((pokemon: PlayerPokemon) => {
if (!pokemon.hp || (pokemon.hp >= pokemon.getMaxHp() && (!this.healStatus || !pokemon.status))) if (!pokemon.hp || (pokemon.hp >= pokemon.getMaxHp() && (!this.healStatus || !pokemon.status)))
return PartyUiHandler.NoEffectMessage; return PartyUiHandler.NoEffectMessage;
return null; return null;
}), iconImage, group || 'potion'); }), iconImage, group || 'potion');
this.restorePoints = restorePoints; this.restorePoints = restorePoints;
this.restorePercent = restorePercent; this.restorePercent = restorePercent;
@ -252,12 +252,12 @@ export class PokemonPpRestoreModifierType extends PokemonMoveModifierType {
constructor(name: string, restorePoints: integer, iconImage?: string) { constructor(name: string, restorePoints: integer, iconImage?: string) {
super(name, `Restores ${restorePoints > -1 ? restorePoints : 'all'} PP for one Pokémon move`, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints), super(name, `Restores ${restorePoints > -1 ? restorePoints : 'all'} PP for one Pokémon move`, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints),
(_pokemon: PlayerPokemon) => { (_pokemon: PlayerPokemon) => {
return null; return null;
}, (pokemonMove: PokemonMove) => { }, (pokemonMove: PokemonMove) => {
if (!pokemonMove.ppUsed) if (!pokemonMove.ppUsed)
return PartyUiHandler.NoEffectMessage; return PartyUiHandler.NoEffectMessage;
return null; return null;
}, iconImage, 'ether'); }, iconImage, 'ether');
this.restorePoints = restorePoints; this.restorePoints = restorePoints;
} }
@ -284,12 +284,12 @@ export class PokemonPpUpModifierType extends PokemonMoveModifierType {
constructor(name: string, upPoints: integer, iconImage?: string) { constructor(name: string, upPoints: integer, iconImage?: string) {
super(name, `Permanently increases PP for one Pokémon move by ${upPoints} for every 5 maximum PP (maximum 3)`, (_type, args) => new Modifiers.PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints), super(name, `Permanently increases PP for one Pokémon move by ${upPoints} for every 5 maximum PP (maximum 3)`, (_type, args) => new Modifiers.PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints),
(_pokemon: PlayerPokemon) => { (_pokemon: PlayerPokemon) => {
return null; return null;
}, (pokemonMove: PokemonMove) => { }, (pokemonMove: PokemonMove) => {
if (pokemonMove.getMove().pp < 5 || pokemonMove.ppUp >= 3) if (pokemonMove.getMove().pp < 5 || pokemonMove.ppUp >= 3)
return PartyUiHandler.NoEffectMessage; return PartyUiHandler.NoEffectMessage;
return null; return null;
}, iconImage, 'ppUp'); }, iconImage, 'ppUp');
this.upPoints = upPoints; this.upPoints = upPoints;
} }
@ -304,7 +304,7 @@ export class PokemonNatureChangeModifierType extends PokemonModifierType {
if (pokemon.getNature() === this.nature) if (pokemon.getNature() === this.nature)
return PartyUiHandler.NoEffectMessage; return PartyUiHandler.NoEffectMessage;
return null; return null;
}), `mint_${Utils.getEnumKeys(Stat).find(s => getNatureStatMultiplier(nature, Stat[s]) > 1)?.toLowerCase() || 'neutral' }`, 'mint'); }), `mint_${Utils.getEnumKeys(Stat).find(s => getNatureStatMultiplier(nature, Stat[s]) > 1)?.toLowerCase() || 'neutral'}`, 'mint');
this.nature = nature; this.nature = nature;
} }
@ -332,6 +332,17 @@ export class DoubleBattleChanceBoosterModifierType extends ModifierType {
} }
} }
export class DoubleBattleChancePreventerModifierType extends ModifierType {
public battleCount: integer;
constructor(name: string, battleCount: integer) {
super(name, `Prevents the chance of an encounter being a double battle for ${battleCount} battles`, (_type, _args) => new Modifiers.DoubleBattleChancePreventerModifier(this, this.battleCount),
null, 'repel');
this.battleCount = battleCount;
}
}
export class TempBattleStatBoosterModifierType extends ModifierType implements GeneratedPersistentModifierType { export class TempBattleStatBoosterModifierType extends ModifierType implements GeneratedPersistentModifierType {
public tempBattleStat: TempBattleStat; public tempBattleStat: TempBattleStat;
@ -345,7 +356,7 @@ export class TempBattleStatBoosterModifierType extends ModifierType implements G
} }
getPregenArgs(): any[] { getPregenArgs(): any[] {
return [ this.tempBattleStat ]; return [this.tempBattleStat];
} }
} }
@ -356,12 +367,12 @@ export class BerryModifierType extends PokemonHeldItemModifierType implements Ge
super(getBerryName(berryType), getBerryEffectDescription(berryType), super(getBerryName(berryType), getBerryEffectDescription(berryType),
(type, args) => new Modifiers.BerryModifier(type, (args[0] as Pokemon).id, berryType), (type, args) => new Modifiers.BerryModifier(type, (args[0] as Pokemon).id, berryType),
null, 'berry'); null, 'berry');
this.berryType = berryType; this.berryType = berryType;
} }
getPregenArgs(): any[] { getPregenArgs(): any[] {
return [ this.berryType ]; return [this.berryType];
} }
} }
@ -420,7 +431,7 @@ export class AttackTypeBoosterModifierType extends PokemonHeldItemModifierType i
} }
getPregenArgs(): any[] { getPregenArgs(): any[] {
return [ this.moveType ]; return [this.moveType];
} }
} }
@ -464,7 +475,7 @@ export class PokemonBaseStatBoosterModifierType extends PokemonHeldItemModifierT
} }
getPregenArgs(): any[] { getPregenArgs(): any[] {
return [ this.stat ]; return [this.stat];
} }
} }
@ -509,7 +520,7 @@ export class PokemonExpBoosterModifierType extends PokemonHeldItemModifierType {
export class PokemonFriendshipBoosterModifierType extends PokemonHeldItemModifierType { export class PokemonFriendshipBoosterModifierType extends PokemonHeldItemModifierType {
constructor(name: string, iconImage?: string) { constructor(name: string, iconImage?: string) {
super(name,'Increases friendship gain per victory by 50%', (_type, args) => new Modifiers.PokemonFriendshipBoosterModifier(this, (args[0] as Pokemon).id), iconImage); super(name, 'Increases friendship gain per victory by 50%', (_type, args) => new Modifiers.PokemonFriendshipBoosterModifier(this, (args[0] as Pokemon).id), iconImage);
} }
} }
@ -545,22 +556,22 @@ export class EvolutionItemModifierType extends PokemonModifierType implements Ge
constructor(evolutionItem: EvolutionItem) { constructor(evolutionItem: EvolutionItem) {
super(Utils.toReadableString(EvolutionItem[evolutionItem]), `Causes certain Pokémon to evolve`, (_type, args) => new Modifiers.EvolutionItemModifier(this, (args[0] as PlayerPokemon).id), super(Utils.toReadableString(EvolutionItem[evolutionItem]), `Causes certain Pokémon to evolve`, (_type, args) => new Modifiers.EvolutionItemModifier(this, (args[0] as PlayerPokemon).id),
(pokemon: PlayerPokemon) => { (pokemon: PlayerPokemon) => {
if (pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId) && pokemonEvolutions[pokemon.species.speciesId].filter(e => e.item === this.evolutionItem if (pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId) && pokemonEvolutions[pokemon.species.speciesId].filter(e => e.item === this.evolutionItem
&& (!e.condition || e.condition.predicate(pokemon))).length) && (!e.condition || e.condition.predicate(pokemon))).length)
return null; return null;
else if (pokemon.isFusion() && pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) && pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(e => e.item === this.evolutionItem else if (pokemon.isFusion() && pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) && pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(e => e.item === this.evolutionItem
&& (!e.condition || e.condition.predicate(pokemon))).length) && (!e.condition || e.condition.predicate(pokemon))).length)
return null; return null;
return PartyUiHandler.NoEffectMessage; return PartyUiHandler.NoEffectMessage;
}, EvolutionItem[evolutionItem].toLowerCase()); }, EvolutionItem[evolutionItem].toLowerCase());
this.evolutionItem = evolutionItem; this.evolutionItem = evolutionItem;
} }
getPregenArgs(): any[] { getPregenArgs(): any[] {
return [ this.evolutionItem ]; return [this.evolutionItem];
} }
} }
@ -569,19 +580,19 @@ export class FormChangeItemModifierType extends PokemonModifierType implements G
constructor(formChangeItem: FormChangeItem) { constructor(formChangeItem: FormChangeItem) {
super(Utils.toReadableString(FormChangeItem[formChangeItem]), `Causes certain Pokémon to change form`, (_type, args) => new Modifiers.PokemonFormChangeItemModifier(this, (args[0] as PlayerPokemon).id, formChangeItem, true), super(Utils.toReadableString(FormChangeItem[formChangeItem]), `Causes certain Pokémon to change form`, (_type, args) => new Modifiers.PokemonFormChangeItemModifier(this, (args[0] as PlayerPokemon).id, formChangeItem, true),
(pokemon: PlayerPokemon) => { (pokemon: PlayerPokemon) => {
if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) && !!pokemonFormChanges[pokemon.species.speciesId].find(fc => fc.trigger.hasTriggerType(SpeciesFormChangeItemTrigger) if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) && !!pokemonFormChanges[pokemon.species.speciesId].find(fc => fc.trigger.hasTriggerType(SpeciesFormChangeItemTrigger)
&& (fc.trigger as SpeciesFormChangeItemTrigger).item === this.formChangeItem)) && (fc.trigger as SpeciesFormChangeItemTrigger).item === this.formChangeItem))
return null; return null;
return PartyUiHandler.NoEffectMessage; return PartyUiHandler.NoEffectMessage;
}, FormChangeItem[formChangeItem].toLowerCase()); }, FormChangeItem[formChangeItem].toLowerCase());
this.formChangeItem = formChangeItem; this.formChangeItem = formChangeItem;
} }
getPregenArgs(): any[] { getPregenArgs(): any[] {
return [ this.formChangeItem ]; return [this.formChangeItem];
} }
} }
@ -623,7 +634,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator {
return null; return null;
let type: Type; let type: Type;
const randInt = Utils.randSeedInt(totalWeight); const randInt = Utils.randSeedInt(totalWeight);
let weight = 0; let weight = 0;
@ -635,7 +646,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator {
} }
weight += typeWeight; weight += typeWeight;
} }
return new AttackTypeBoosterModifierType(type, 20); return new AttackTypeBoosterModifierType(type, 20);
}); });
} }
@ -711,7 +722,7 @@ export class TerastallizeModifierType extends PokemonHeldItemModifierType implem
} }
getPregenArgs(): any[] { getPregenArgs(): any[] {
return [ this.teraType ]; return [this.teraType];
} }
} }
@ -784,7 +795,7 @@ export const modifierTypes = {
HYPER_POTION: () => new PokemonHpRestoreModifierType('Hyper Potion', 200, 50), HYPER_POTION: () => new PokemonHpRestoreModifierType('Hyper Potion', 200, 50),
MAX_POTION: () => new PokemonHpRestoreModifierType('Max Potion', 0, 100), MAX_POTION: () => new PokemonHpRestoreModifierType('Max Potion', 0, 100),
FULL_RESTORE: () => new PokemonHpRestoreModifierType('Full Restore', 0, 100, true), FULL_RESTORE: () => new PokemonHpRestoreModifierType('Full Restore', 0, 100, true),
REVIVE: () => new PokemonReviveModifierType('Revive', 50), REVIVE: () => new PokemonReviveModifierType('Revive', 50),
MAX_REVIVE: () => new PokemonReviveModifierType('Max Revive', 100), MAX_REVIVE: () => new PokemonReviveModifierType('Max Revive', 100),
@ -804,9 +815,9 @@ export const modifierTypes = {
PP_UP: () => new PokemonPpUpModifierType('PP Up', 1), PP_UP: () => new PokemonPpUpModifierType('PP Up', 1),
PP_MAX: () => new PokemonPpUpModifierType('PP Max', 3), PP_MAX: () => new PokemonPpUpModifierType('PP Max', 3),
/*REPEL: () => new DoubleBattleChanceBoosterModifierType('Repel', 5), REPEL: () => new DoubleBattleChancePreventerModifierType('Repel', 5),
SUPER_REPEL: () => new DoubleBattleChanceBoosterModifierType('Super Repel', 10), SUPER_REPEL: () => new DoubleBattleChancePreventerModifierType('Super Repel', 10),
MAX_REPEL: () => new DoubleBattleChanceBoosterModifierType('Max Repel', 25),*/ MAX_REPEL: () => new DoubleBattleChancePreventerModifierType('Max Repel', 25),
LURE: () => new DoubleBattleChanceBoosterModifierType('Lure', 5), LURE: () => new DoubleBattleChanceBoosterModifierType('Lure', 5),
SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType('Super Lure', 10), SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType('Super Lure', 10),
@ -937,7 +948,7 @@ export const modifierTypes = {
DNA_SPLICERS: () => new FusePokemonModifierType('DNA Splicers'), DNA_SPLICERS: () => new FusePokemonModifierType('DNA Splicers'),
MINI_BLACK_HOLE: () => new TurnHeldItemTransferModifierType('Mini Black Hole'), MINI_BLACK_HOLE: () => new TurnHeldItemTransferModifierType('Mini Black Hole'),
VOUCHER: () => new AddVoucherModifierType(VoucherType.REGULAR, 1), VOUCHER: () => new AddVoucherModifierType(VoucherType.REGULAR, 1),
VOUCHER_PLUS: () => new AddVoucherModifierType(VoucherType.PLUS, 1), VOUCHER_PLUS: () => new AddVoucherModifierType(VoucherType.PLUS, 1),
VOUCHER_PREMIUM: () => new AddVoucherModifierType(VoucherType.PREMIUM, 1), VOUCHER_PREMIUM: () => new AddVoucherModifierType(VoucherType.PREMIUM, 1),
@ -983,7 +994,14 @@ const modifierPool: ModifierPool = {
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3); const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
return thresholdPartyMemberCount; return thresholdPartyMemberCount;
}, 3), }, 3),
new WeightedModifierType(modifierTypes.LURE, 2), new WeightedModifierType(modifierTypes.REPEL, (party: Pokemon[]) => {
const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType);
return existingItem ? 0 : 2;
}),
new WeightedModifierType(modifierTypes.LURE, (party: Pokemon[]) => {
const existingItem = party[0].scene.findModifier(m => m.type instanceof DoubleBattleChancePreventerModifierType || m.type instanceof DoubleBattleChanceBoosterModifierType);
return existingItem ? 0 : 2;
}),
new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4), new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4),
new WeightedModifierType(modifierTypes.BERRY, 2), new WeightedModifierType(modifierTypes.BERRY, 2),
new WeightedModifierType(modifierTypes.TM_COMMON, 1), new WeightedModifierType(modifierTypes.TM_COMMON, 1),
@ -1169,8 +1187,8 @@ const enemyBuffModifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 5), new WeightedModifierType(modifierTypes.ENEMY_ENDURE_CHANCE, 5),
new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 300) new WeightedModifierType(modifierTypes.ENEMY_FUSED_CHANCE, 300)
].map(m => { m.setTier(ModifierTier.ULTRA); return m; }), ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
[ModifierTier.ROGUE]: [ ].map(m => { m.setTier(ModifierTier.ROGUE); return m; }), [ModifierTier.ROGUE]: [].map(m => { m.setTier(ModifierTier.ROGUE); return m; }),
[ModifierTier.MASTER]: [ ].map(m => { m.setTier(ModifierTier.MASTER); return m; }) [ModifierTier.MASTER]: [].map(m => { m.setTier(ModifierTier.MASTER); return m; })
}; };
const dailyStarterModifierPool: ModifierPool = { const dailyStarterModifierPool: ModifierPool = {
@ -1240,11 +1258,11 @@ export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool
return pool; return pool;
} }
const tierWeights = [ 769 / 1024, 192 / 1024, 48 / 1024, 12 / 1024, 1 / 1024 ]; const tierWeights = [769 / 1024, 192 / 1024, 48 / 1024, 12 / 1024, 1 / 1024];
export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount: integer = 0) { export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount: integer = 0) {
const pool = getModifierPoolForType(poolType); const pool = getModifierPoolForType(poolType);
const ignoredIndexes = {}; const ignoredIndexes = {};
const modifierTableData = {}; const modifierTableData = {};
const thresholds = Object.fromEntries(new Map(Object.keys(pool).map(t => { const thresholds = Object.fromEntries(new Map(Object.keys(pool).map(t => {
@ -1256,6 +1274,7 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod
pool[t].reduce((total: integer, modifierType: WeightedModifierType) => { pool[t].reduce((total: integer, modifierType: WeightedModifierType) => {
const weightedModifierType = modifierType as WeightedModifierType; const weightedModifierType = modifierType as WeightedModifierType;
const existingModifiers = party[0].scene.findModifiers(m => (m.type.generatorId || m.type.id) === weightedModifierType.modifierType.id, poolType === ModifierPoolType.PLAYER); const existingModifiers = party[0].scene.findModifiers(m => (m.type.generatorId || m.type.id) === weightedModifierType.modifierType.id, poolType === ModifierPoolType.PLAYER);
existingModifiers.forEach(m => console.log(m.type.name))
const itemModifierType = weightedModifierType.modifierType instanceof ModifierTypeGenerator const itemModifierType = weightedModifierType.modifierType instanceof ModifierTypeGenerator
? weightedModifierType.modifierType.generateType(party) ? weightedModifierType.modifierType.generateType(party)
: weightedModifierType.modifierType; : weightedModifierType.modifierType;
@ -1285,7 +1304,7 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod
}, 0); }, 0);
for (let id of tierModifierIds) for (let id of tierModifierIds)
modifierTableData[id].tierPercent = Math.floor((modifierTableData[id].weight / tierMaxWeight) * 10000) / 100; modifierTableData[id].tierPercent = Math.floor((modifierTableData[id].weight / tierMaxWeight) * 10000) / 100;
return [ t, Object.fromEntries(thresholds) ]; return [t, Object.fromEntries(thresholds)];
}))); })));
for (let id of Object.keys(modifierTableData)) { for (let id of Object.keys(modifierTableData)) {
modifierTableData[id].totalPercent = Math.floor(modifierTableData[id].tierPercent * tierWeights[modifierTableData[id].tier] * 100) / 100; modifierTableData[id].totalPercent = Math.floor(modifierTableData[id].tierPercent * tierWeights[modifierTableData[id].tier] * 100) / 100;
@ -1480,7 +1499,7 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType,
if (index === undefined) if (index === undefined)
return null; return null;
if (player) if (player)
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier]) console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier])
let modifierType: ModifierType = (pool[tier][index]).modifierType; let modifierType: ModifierType = (pool[tier][index]).modifierType;
@ -1523,7 +1542,7 @@ export function getPartyLuckValue(party: Pokemon[]): integer {
} }
export function getLuckString(luckValue: integer): string { export function getLuckString(luckValue: integer): string {
return [ 'D', 'C', 'C+', 'B-', 'B', 'B+', 'A-', 'A', 'A+', 'A++', 'S', 'S+', 'SS', 'SS+', 'SSS' ][luckValue]; return ['D', 'C', 'C+', 'B-', 'B', 'B+', 'A-', 'A', 'A+', 'A++', 'S', 'S+', 'SS', 'SS+', 'SSS'][luckValue];
} }
export function getLuckTextTint(luckValue: integer): integer { export function getLuckTextTint(luckValue: integer): integer {

View File

@ -310,6 +310,32 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier
} }
} }
export class DoubleBattleChancePreventerModifier extends LapsingPersistentModifier {
constructor(type: ModifierTypes.DoubleBattleChancePreventerModifierType, battlesLeft: integer, stackCount?: integer) {
super(type, battlesLeft, stackCount);
}
match(modifier: Modifier): boolean {
if (modifier instanceof DoubleBattleChancePreventerModifier)
return (modifier as DoubleBattleChancePreventerModifier).battlesLeft === this.battlesLeft;
return false;
}
clone(): DoubleBattleChancePreventerModifier {
return new DoubleBattleChancePreventerModifier(this.type as ModifierTypes.DoubleBattleChancePreventerModifierType, this.battlesLeft, this.stackCount);
}
getArgs(): any[] {
return [ this.battlesLeft ];
}
apply(args: any[]): boolean {
const doubleBattleChance = args[0] as Utils.NumberHolder;
doubleBattleChance.value = 0;
return true;
}
}
export class TempBattleStatBoosterModifier extends LapsingPersistentModifier { export class TempBattleStatBoosterModifier extends LapsingPersistentModifier {
private tempBattleStat: TempBattleStat; private tempBattleStat: TempBattleStat;