diff --git a/public/audio/bgm/swamp.mp3 b/public/audio/bgm/swamp.mp3 index ea6e985c0..074e1c3d8 100644 Binary files a/public/audio/bgm/swamp.mp3 and b/public/audio/bgm/swamp.mp3 differ diff --git a/public/audio/bgm/long_grass.mp3 b/public/audio/bgm/tall_grass.mp3 similarity index 100% rename from public/audio/bgm/long_grass.mp3 rename to public/audio/bgm/tall_grass.mp3 diff --git a/src/battle-info.ts b/src/battle-info.ts index 19810afaa..0cf7d5267 100644 --- a/src/battle-info.ts +++ b/src/battle-info.ts @@ -102,8 +102,11 @@ export default class BattleInfo extends Phaser.GameObjects.Container { } updateInfo(pokemon: Pokemon, callback?: Function) { - if (!this.scene) + if (!this.scene) { + if (callback) + callback(); return; + } const updatePokemonHp = () => { const duration = Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000); @@ -158,8 +161,9 @@ export default class BattleInfo extends Phaser.GameObjects.Container { const relLevelExp = getLevelRelExp(this.lastLevel + 1, battler.species.growthRate); const levelExp = levelUp ? relLevelExp : battler.levelExp; let ratio = levelExp / relLevelExp; - let duration = ((levelExp - this.lastLevelExp) / relLevelExp) * 1650; - this.scene.sound.play('exp'); + let duration = this.visible ? ((levelExp - this.lastLevelExp) / relLevelExp) * 1650 : 0; + if (duration) + this.scene.sound.play('exp'); this.scene.tweens.add({ targets: this.expBar, ease: 'Sine.easeIn', @@ -179,7 +183,8 @@ export default class BattleInfo extends Phaser.GameObjects.Container { } }, onComplete: () => { - this.scene.sound.stopByKey('exp'); + if (duration) + this.scene.sound.stopByKey('exp'); if (ratio === 1) { this.lastLevelExp = 0; this.lastLevel++; diff --git a/src/battle-phase.ts b/src/battle-phase.ts index bd859d75a..f9f643177 100644 --- a/src/battle-phase.ts +++ b/src/battle-phase.ts @@ -9,7 +9,7 @@ import { ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, getModifie import PartyUiHandler from "./ui/party-ui-handler"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor as getPokeballTintColor, PokeballType } from "./pokeball"; import { pokemonLevelMoves } from "./pokemon-level-moves"; -import { MoveAnim, loadMoveAnimAssets } from "./battle-anims"; +import { MoveAnim, initAnim, loadMoveAnimAssets } from "./battle-anims"; import { StatusEffect } from "./status-effect"; export class BattlePhase { @@ -776,10 +776,12 @@ export class LearnMovePhase extends PartyMemberPokemonPhase { if (pokemon.moveset.length < 4) { pokemon.moveset.push(new PokemonMove(this.moveId, 0, 0)); - loadMoveAnimAssets(this.scene, [ this.moveId ]) - .then(() => { - this.scene.sound.play('level_up_fanfare'); - this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), null, true); + initAnim(this.moveId).then(() => { + loadMoveAnimAssets(this.scene, [ this.moveId ], true) + .then(() => { + this.scene.sound.play('level_up_fanfare'); + this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), null, true); + }); }); } else this.end(); @@ -965,16 +967,14 @@ export class SelectModifierPhase extends BattlePhase { this.scene.ui.setModeWithoutClear(Mode.PARTY, false, (slotIndex: integer) => { if (slotIndex < 6) { this.scene.ui.setMode(Mode.MODIFIER_SELECT); - this.scene.addModifier(types[cursor].newModifier(this.scene.getParty()[slotIndex])); + this.scene.addModifier(types[cursor].newModifier(this.scene.getParty()[slotIndex])).then(() => super.end()); this.scene.ui.setMode(Mode.MESSAGE); - super.end(); } else this.scene.ui.setMode(Mode.MODIFIER_SELECT); }, pokemonModifierType.selectFilter); } else { - this.scene.addModifier(types[cursor].newModifier()) + this.scene.addModifier(types[cursor].newModifier()).then(() => super.end()); this.scene.ui.setMode(Mode.MESSAGE); - super.end(); } }); } diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 0b6564eac..90aafd5d3 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -410,31 +410,44 @@ export default class BattleScene extends Phaser.Scene { this.phaseQueue.push(new CommandPhase(this)); } - addModifier(modifier: Modifier): void { - if (modifier.add(this.modifierBar, this.modifiers)) - this.sound.play('restore'); + addModifier(modifier: Modifier): Promise { + return new Promise(resolve => { + if (modifier.add(this.modifierBar, this.modifiers)) + this.sound.play('restore'); - if (modifier instanceof ConsumableModifier) { - const args = [ this ]; - if (modifier.shouldApply(args)) - modifier.apply(args); - return; - } - - if (modifier instanceof PokemonModifier) { - for (let p in this.party) { - const pokemon = this.party[p]; - - if (modifier instanceof ConsumablePokemonModifier) { - const args = [ pokemon ]; - if (modifier.shouldApply(args)) - modifier.apply(args); - } - - pokemon.calculateStats(); - pokemon.updateInfo(); + if (modifier instanceof ConsumableModifier) { + const args = [ this ]; + if (modifier.shouldApply(args)) + modifier.apply(args); + resolve(); + return; } - } + + let pokemonToUpdate = 0; + + if (modifier instanceof PokemonModifier) { + for (let p in this.party) { + const pokemon = this.party[p]; + + if (modifier instanceof ConsumablePokemonModifier) { + const args = [ pokemon ]; + if (modifier.shouldApply(args)) + modifier.apply(args); + } + + pokemonToUpdate++; + + pokemon.calculateStats(); + pokemon.updateInfo(() => { + if (!(--pokemonToUpdate)) + resolve(); + }); + } + } + + if (!pokemonToUpdate) + resolve(); + }); } getModifier(modifierType: { new(...args: any[]): Modifier }): Modifier { diff --git a/src/modifier.ts b/src/modifier.ts index 07b3e495f..57e5cbfac 100644 --- a/src/modifier.ts +++ b/src/modifier.ts @@ -1,4 +1,6 @@ +import { LevelUpPhase } from "./battle-phase"; import BattleScene from "./battle-scene"; +import { getLevelTotalExp } from "./exp"; import { getPokeballName, PokeballType } from "./pokeball"; import Pokemon, { PlayerPokemon } from "./pokemon"; import { Stat, getStatName } from "./pokemon-stat"; @@ -240,6 +242,24 @@ export class PokemonHpRestoreModifier extends ConsumablePokemonModifier { } } +export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier { + constructor(type: ModifierType, pokemonId: integer) { + super(type, pokemonId); + } + + apply(args: any[]): boolean { + const pokemon = args[0] as PlayerPokemon; + pokemon.level++; + pokemon.exp = getLevelTotalExp(pokemon.level, pokemon.species.growthRate); + pokemon.levelExp = 0; + + const scene = pokemon.scene as BattleScene; + scene.unshiftPhase(new LevelUpPhase(scene, scene.getParty().indexOf(pokemon), pokemon.level)); + + return true; + } +} + export class ExpBoosterModifier extends Modifier { private boostMultiplier: integer; @@ -376,22 +396,34 @@ export abstract class PokemonModifierType extends ModifierType { export class PokemonHpRestoreModifierType extends PokemonModifierType { protected restorePercent: integer; - constructor(name: string, restorePercent: integer, newModifierFunc?: Function, iconImage?: string) { + constructor(name: string, restorePercent: integer, newModifierFunc?: Function, selectFilter?: Function, iconImage?: string) { super(name, `Restore ${restorePercent} HP or ${restorePercent}% HP for one POKéMON, whichever is higher`, newModifierFunc || ((_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePercent, false)), - (pokemon: PlayerPokemon) => { - if (pokemon.hp >= pokemon.getMaxHp()) + selectFilter || ((pokemon: PlayerPokemon) => { + if (!pokemon.hp || pokemon.hp >= pokemon.getMaxHp()) return PartyUiHandler.NoEffectMessage; return null; - }, iconImage); + }), iconImage); this.restorePercent = restorePercent; } } +export class PokemonLevelIncrementModifierType extends PokemonModifierType { + constructor(name: string, iconImage?: string) { + super(name, `Increase a POKéMON\'s level by 1`, (type, args) => new PokemonLevelIncrementModifier(type, (args[0] as PlayerPokemon).id), + (_pokemon: PlayerPokemon) => null, iconImage); + } +} + export class PokemonReviveModifierType extends PokemonHpRestoreModifierType { constructor(name: string, restorePercent: integer, iconImage?: string) { - super(name, restorePercent, (_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePercent, true), iconImage); + super(name, restorePercent, (_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePercent, true), + ((pokemon: PlayerPokemon) => { + if (pokemon.hp) + return PartyUiHandler.NoEffectMessage; + return null; + }), iconImage); this.description = `Revive one POKéMON and restore ${restorePercent}% HP`; this.selectFilter = (pokemon: PlayerPokemon) => { @@ -471,6 +503,7 @@ const modifierPool = { const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.6).length; return thresholdPartyMemberCount; }), + new PokemonLevelIncrementModifierType('RARE CANDY'), new PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP), new PokemonBaseStatBoosterModifierType('PROTEIN', Stat.ATK), new PokemonBaseStatBoosterModifierType('IRON', Stat.DEF),