[Bug] Fix weather form changes not changing with weather abilities

https://github.com/pagefaultgames/pokerogue/pull/5857

* Add test for forecast

* Fix PostSummonFormChangeByWeatherAbAttr

* Fix overrides in forecast test

* Remove a test whose trigger conditions can no longer happen

* Update src/data/abilities/ability.ts

Co-authored-by: Dean <69436131+emdeann@users.noreply.github.com>

* Fix missing tsdoc param

* Apply kev's suggestions from code review

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Simplify PostSummonFormChangeByWeather's canApplyPostSummon

* Fix unused params that messed up after rebase

* Fix form change import

Messed up due to improper rebase

---------

Co-authored-by: Dean <69436131+emdeann@users.noreply.github.com>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
Sirz Benjie 2025-06-16 08:02:09 -05:00 committed by GitHub
parent e3108603e3
commit 6ff258fb37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 41 deletions

View File

@ -24,11 +24,11 @@ import { allMoves } from "../data-lists";
import { ArenaTagSide } from "#enums/arena-tag-side"; import { ArenaTagSide } from "#enums/arena-tag-side";
import { BerryModifier, HitHealModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; import { BerryModifier, HitHealModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
import { TerrainType } from "#app/data/terrain"; import { TerrainType } from "#app/data/terrain";
import { pokemonFormChanges } from "../pokemon-forms";
import { import {
SpeciesFormChangeRevertWeatherFormTrigger,
SpeciesFormChangeWeatherTrigger, SpeciesFormChangeWeatherTrigger,
SpeciesFormChangeAbilityTrigger,
} from "../pokemon-forms/form-change-triggers"; } from "../pokemon-forms/form-change-triggers";
import { SpeciesFormChangeAbilityTrigger } from "../pokemon-forms/form-change-triggers";
import i18next from "i18next"; import i18next from "i18next";
import { Command } from "#enums/command"; import { Command } from "#enums/command";
import { BerryModifierType } from "#app/modifier/modifier-type"; import { BerryModifierType } from "#app/modifier/modifier-type";
@ -3971,27 +3971,32 @@ export class PostSummonFormChangeByWeatherAbAttr extends PostSummonAbAttr {
this.ability = ability; this.ability = ability;
} }
/**
* Determine if the pokemon has a forme change that is triggered by the weather
*
* @param pokemon - The pokemon with the forme change ability
* @param _passive - unused
* @param _simulated - unused
* @param _args - unused
*/
override canApplyPostSummon(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _args: any[]): boolean { override canApplyPostSummon(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _args: any[]): boolean {
const isCastformWithForecast = return !!pokemonFormChanges[pokemon.species.speciesId]?.some(
pokemon.species.speciesId === SpeciesId.CASTFORM && this.ability === AbilityId.FORECAST; fc => fc.findTrigger(SpeciesFormChangeWeatherTrigger) && fc.canChange(pokemon),
const isCherrimWithFlowerGift = );
pokemon.species.speciesId === SpeciesId.CHERRIM && this.ability === AbilityId.FLOWER_GIFT;
return isCastformWithForecast || isCherrimWithFlowerGift;
} }
/** /**
* Calls the {@linkcode BattleScene.triggerPokemonFormChange | triggerPokemonFormChange} for both * Trigger the pokemon's forme change by invoking
* {@linkcode SpeciesFormChange.SpeciesFormChangeWeatherTrigger | SpeciesFormChangeWeatherTrigger} and * {@linkcode BattleScene.triggerPokemonFormChange | triggerPokemonFormChange}
* {@linkcode SpeciesFormChange.SpeciesFormChangeWeatherTrigger | SpeciesFormChangeRevertWeatherFormTrigger} if it *
* is the specific Pokemon and ability * @param pokemon - The Pokemon with this ability
* @param {Pokemon} pokemon the Pokemon with this ability * @param _passive - unused
* @param _passive n/a * @param simulated - unused
* @param _args n/a * @param _args - unused
*/ */
override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void { override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void {
if (!simulated) { if (!simulated) {
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeWeatherTrigger); globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeWeatherTrigger);
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeRevertWeatherFormTrigger);
} }
} }
} }
@ -5301,10 +5306,11 @@ export class PostWeatherChangeFormChangeAbAttr extends PostWeatherChangeAbAttr {
/** /**
* Calls {@linkcode Arena.triggerWeatherBasedFormChangesToNormal | triggerWeatherBasedFormChangesToNormal} when the * Calls {@linkcode Arena.triggerWeatherBasedFormChangesToNormal | triggerWeatherBasedFormChangesToNormal} when the
* weather changed to form-reverting weather, otherwise calls {@linkcode Arena.triggerWeatherBasedFormChanges | triggerWeatherBasedFormChanges} * weather changed to form-reverting weather, otherwise calls {@linkcode Arena.triggerWeatherBasedFormChanges | triggerWeatherBasedFormChanges}
* @param {Pokemon} _pokemon the Pokemon with this ability * @param _pokemon - The Pokemon with this ability
* @param _passive n/a * @param _passive - unused
* @param _weather n/a * @param simulated - unused
* @param _args n/a * @param _weather - unused
* @param _args - unused
*/ */
override applyPostWeatherChange( override applyPostWeatherChange(
_pokemon: Pokemon, _pokemon: Pokemon,

View File

@ -21,26 +21,10 @@ describe("Abilities - Forecast", () => {
const RAINY_FORM = 2; const RAINY_FORM = 2;
const SNOWY_FORM = 3; const SNOWY_FORM = 3;
/**
* Tests form changes based on weather changes
* @param {GameManager} game The game manager instance
* @param {WeatherType} weather The active weather to set
* @param form The expected form based on the active weather
* @param initialForm The initial form pre form change
*/
const testWeatherFormChange = async (game: GameManager, weather: WeatherType, form: number, initialForm?: number) => {
game.override.weather(weather).starterForms({ [SpeciesId.CASTFORM]: initialForm });
await game.classicMode.startBattle([SpeciesId.CASTFORM]);
game.move.select(MoveId.SPLASH);
expect(game.scene.getPlayerPokemon()?.formIndex).toBe(form);
};
/** /**
* Tests reverting to normal form when Cloud Nine/Air Lock is active on the field * Tests reverting to normal form when Cloud Nine/Air Lock is active on the field
* @param {GameManager} game The game manager instance * @param game - The game manager instance
* @param {AbilityId} ability The ability that is active on the field * @param ability - The ability that is active on the field
*/ */
const testRevertFormAgainstAbility = async (game: GameManager, ability: AbilityId) => { const testRevertFormAgainstAbility = async (game: GameManager, ability: AbilityId) => {
game.override.starterForms({ [SpeciesId.CASTFORM]: SUNNY_FORM }).enemyAbility(ability); game.override.starterForms({ [SpeciesId.CASTFORM]: SUNNY_FORM }).enemyAbility(ability);
@ -191,10 +175,6 @@ describe("Abilities - Forecast", () => {
30 * 1000, 30 * 1000,
); );
it("reverts to Normal Form during Clear weather", async () => {
await testWeatherFormChange(game, WeatherType.NONE, NORMAL_FORM, SUNNY_FORM);
});
it("reverts to Normal Form if a Pokémon on the field has Air Lock", async () => { it("reverts to Normal Form if a Pokémon on the field has Air Lock", async () => {
await testRevertFormAgainstAbility(game, AbilityId.AIR_LOCK); await testRevertFormAgainstAbility(game, AbilityId.AIR_LOCK);
}); });
@ -277,4 +257,20 @@ describe("Abilities - Forecast", () => {
expect(castform.formIndex).toBe(NORMAL_FORM); expect(castform.formIndex).toBe(NORMAL_FORM);
}); });
// NOTE: The following pairs of tests are intentionally testing the same scenario, switching the player and enemy pokemon
// as this is a regression test where the order of player and enemy mattered.
it("should trigger player's form change when summoned at the same time as an enemy with a weather changing ability", async () => {
game.override.enemyAbility(AbilityId.DROUGHT);
await game.classicMode.startBattle([SpeciesId.CASTFORM, SpeciesId.MAGIKARP]);
const castform = game.scene.getPlayerPokemon()!;
expect(castform.formIndex).toBe(SUNNY_FORM);
});
it("should trigger enemy's form change when summoned at the same time as a player with a weather changing ability", async () => {
game.override.ability(AbilityId.DROUGHT).enemySpecies(SpeciesId.CASTFORM).enemyAbility(AbilityId.FORECAST);
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
const castform = game.scene.getEnemyPokemon()!;
expect(castform.formIndex).toBe(SUNNY_FORM);
});
}); });