diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 35c7951c344..0efc4dc8ddb 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -55,7 +55,6 @@ import PokemonInfoContainer from './ui/pokemon-info-container'; import { biomeDepths } from './data/biomes'; import { initTouchControls } from './touch-controls'; import { UiTheme } from './enums/ui-theme'; -import CacheBustedLoaderPlugin from './plugins/cache-busted-loader-plugin'; import { SceneBase } from './scene-base'; import CandyBar from './ui/candy-bar'; @@ -214,8 +213,6 @@ export default class BattleScene extends SceneBase { this.phaseQueuePrepend = []; this.phaseQueuePrependSpliceIndex = -1; this.nextCommandPhaseQueue = []; - - Phaser.Plugins.PluginCache.register('Loader', CacheBustedLoaderPlugin, 'load'); } loadPokemonAtlas(key: string, atlasPath: string, experimental?: boolean) { diff --git a/src/data/ability.ts b/src/data/ability.ts index 2ad6959cbd7..a0645d4af9c 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2563,7 +2563,8 @@ export function initAbilities() { new Ability(Abilities.BULLETPROOF, "Bulletproof", "Protects the Pokémon from some ball and bomb moves.", 6) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.BALLBOMB_MOVE)) .ignorable(), - new Ability(Abilities.COMPETITIVE, "Competitive (N)", "Boosts the Sp. Atk stat sharply when a stat is lowered.", 6), + new Ability(Abilities.COMPETITIVE, "Competitive", "Boosts the Sp. Atk stat sharply when a stat is lowered.", 6) + .attr(PostStatChangeStatChangeAbAttr, (target, statsChanged, levels) => levels < 0, [BattleStat.SPATK], 2), new Ability(Abilities.STRONG_JAW, "Strong Jaw", "The Pokémon's strong jaw boosts the power of its biting moves.", 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5), new Ability(Abilities.REFRIGERATE, "Refrigerate", "Normal-type moves become Ice-type moves. The power of those moves is boosted a little.", 6) diff --git a/src/data/move.ts b/src/data/move.ts index e5ff01c638f..e4eed04b8ae 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -23,6 +23,7 @@ import { SpeciesFormChangeActiveTrigger } from "./pokemon-forms"; import { Species } from "./enums/species"; import { ModifierPoolType } from "#app/modifier/modifier-type"; import { Command } from "../ui/command-ui-handler"; +import { Biome } from "./enums/biome"; export enum MoveCategory { PHYSICAL, @@ -2745,6 +2746,98 @@ export class RandomMoveAttr extends OverrideMoveEffectAttr { } } +export class NaturePowerAttr extends OverrideMoveEffectAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise { + return new Promise(resolve => { + var moveId; + switch (user.scene.arena.getTerrainType()) { + // this allows terrains to 'override' the biome move + case TerrainType.NONE: + switch (user.scene.arena.biomeType) { + case Biome.TOWN: + moveId = Moves.TRI_ATTACK; + break; + case Biome.PLAINS + || Biome.GRASS + || Biome.TALL_GRASS + || Biome.MEADOW + || Biome.FOREST + || Biome.JUNGLE: + moveId = Moves.ENERGY_BALL; + break; + case Biome.SEA + || Biome.SWAMP + || Biome.BEACH + || Biome.LAKE + || Biome.SEABED + || Biome.ISLAND: + moveId = Moves.HYDRO_PUMP; + break; + case Biome.MOUNTAIN: + moveId = Moves.AIR_SLASH; + break; + case Biome.BADLANDS + || Biome.DESERT + || Biome.WASTELAND + || Biome.CONSTRUCTION_SITE: + moveId = Moves.EARTH_POWER; + break; + case Biome.CAVE: + moveId = Moves.POWER_GEM; + break; + case Biome.ICE_CAVE + || Biome.SNOWY_FOREST: + moveId = Moves.ICE_BEAM; + break; + case Biome.VOLCANO: + moveId = Moves.FLAMETHROWER; + break; + case Biome.GRAVEYARD + || Biome.RUINS + || Biome.TEMPLE: + moveId = Moves.SHADOW_BALL; + break; + case Biome.DOJO: + moveId = Moves.AURA_SPHERE; + break; + case Biome.FAIRY_CAVE: + moveId = Moves.MOONBLAST; + break; + case Biome.ABYSS + || Biome.SPACE + || Biome.END: + moveId = Moves.DARK_PULSE; + break; + } + break; + case TerrainType.MISTY: + moveId = Moves.MOONBLAST; + break; + case TerrainType.ELECTRIC: + moveId = Moves.THUNDERBOLT; + break; + case TerrainType.GRASSY: + moveId = Moves.ENERGY_BALL; + break; + case TerrainType.PSYCHIC: + moveId = Moves.PSYCHIC; + break; + default: + // Just in case there's no match + moveId = Moves.TRI_ATTACK; + break; + } + + user.getMoveQueue().push({ move: moveId, targets: [target.getBattlerIndex()], ignorePP: true }); + user.scene.unshiftPhase(new MovePhase(user.scene, user, [target.getBattlerIndex()], new PokemonMove(moveId, 0, 0, true), true)); + initMoveAnim(moveId).then(() => { + loadMoveAnimAssets(user.scene, [ moveId ], true) + .then(() => resolve(true)); + }); + }); + } +} + const lastMoveCopiableCondition: MoveConditionFunc = (user, target, move) => { const copiableMove = user.scene.currentBattle.lastMove; @@ -3875,7 +3968,9 @@ export function initMoves() { .attr(MovePowerMultiplierAttr, (user, target, move) => target.status?.effect === StatusEffect.PARALYSIS ? 2 : 1) .attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS), new SelfStatusMove(Moves.FOLLOW_ME, "Follow Me (N)", Type.NORMAL, -1, 20, "The user draws attention to itself, making all targets take aim only at the user.", -1, 2, 3), - new StatusMove(Moves.NATURE_POWER, "Nature Power (N)", Type.NORMAL, -1, 20, "This attack makes use of nature's power. Its effects vary depending on the user's environment.", -1, 0, 3), + new StatusMove(Moves.NATURE_POWER, "Nature Power", Type.NORMAL, -1, 20, "This attack makes use of nature's power. Its effects vary depending on the user's environment.", -1, 0, 3) + .attr(NaturePowerAttr) + .ignoresVirtual(), new SelfStatusMove(Moves.CHARGE, "Charge (P)", Type.ELECTRIC, -1, 20, "The user boosts the power of the Electric move it uses on the next turn. This also raises the user's Sp. Def stat.", -1, 0, 3) .attr(StatChangeAttr, BattleStat.SPDEF, 1, true), new StatusMove(Moves.TAUNT, "Taunt (N)", Type.DARK, 100, 20, "The target is taunted into a rage that allows it to use only attack moves for three turns.", -1, 0, 3), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index c396ca37bcc..16e695769e7 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -850,10 +850,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return true; }); } else - levelMoves = this.getSpeciesForm().getLevelMoves(); + levelMoves = this.getSpeciesForm(true).getLevelMoves(); if (this.fusionSpecies) { const evolutionLevelMoves = levelMoves.slice(0, Math.max(levelMoves.findIndex(lm => !!lm[0]), 0)); - const fusionLevelMoves = this.getFusionSpeciesForm().getLevelMoves(); + const fusionLevelMoves = this.getFusionSpeciesForm(true).getLevelMoves(); const newLevelMoves: LevelMoves = []; while (levelMoves.length && levelMoves[0][0] < startingLevel) levelMoves.shift(); @@ -1186,7 +1186,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyMoveAttrs(HighCritAttr, source, this, move, critLevel); this.scene.applyModifiers(TempBattleStatBoosterModifier, source.isPlayer(), TempBattleStat.CRIT, critLevel); const bonusCrit = new Utils.BooleanHolder(false); - if (applyAbAttrs(BonusCritAbAttr, this, null, bonusCrit)) { + if (applyAbAttrs(BonusCritAbAttr, source, null, bonusCrit)) { if (bonusCrit.value) critLevel.value += 1; } @@ -2260,6 +2260,7 @@ export class PlayerPokemon extends Pokemon { if (newEvolution.condition.predicate(this)) { const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.ivs, this.nature); newPokemon.natureOverride = this.natureOverride; + newPokemon.moveset = this.moveset.slice(); newPokemon.fusionSpecies = this.fusionSpecies; newPokemon.fusionFormIndex = this.fusionFormIndex; newPokemon.fusionAbilityIndex = this.fusionAbilityIndex; diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 9a3b7fdd5bd..a3b92112990 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -3,6 +3,7 @@ import { Biome } from "./data/enums/biome"; import { TrainerType } from "./data/enums/trainer-type"; import { trainerConfigs } from "./data/trainer-config"; import { getBiomeHasProps } from "./field/arena"; +import CacheBustedLoaderPlugin from "./plugins/cache-busted-loader-plugin"; import { SceneBase } from "./scene-base"; import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme"; import * as Utils from "./utils"; @@ -10,6 +11,8 @@ import * as Utils from "./utils"; export class LoadingScene extends SceneBase { constructor() { super('loading'); + + Phaser.Plugins.PluginCache.register('Loader', CacheBustedLoaderPlugin, 'load'); } preload() {