[Balance] Add faint trigger to various form changes (#6122)

* [Balance] Add faint trigger to Battle Bond Greninja's form change

The form change functionality will now be slightly closer to Generation 7/8, as the Greninja will now revert from Ash form to Battle Bond form upon fainting.

* Change how the form change on faint is triggered

It is no longer directly handled by the faint phase, and is instead part of the abilities now, as more than Battle Bond Greninja revert via this method (Disguise Mimikyu, Power Construct Zygarde).

* Adjust Disguise test
This commit is contained in:
Madmadness65 2025-07-20 13:59:01 -05:00 committed by GitHub
parent 8dd6608e10
commit 1428d8b870
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 5 deletions

View File

@ -5305,6 +5305,26 @@ export class PostFaintUnsuppressedWeatherFormChangeAbAttr extends PostFaintAbAtt
} }
} }
export class PostFaintFormChangeAbAttr extends PostFaintAbAttr {
private formFunc: (p: Pokemon) => number;
constructor(formFunc: (p: Pokemon) => number) {
super(true);
this.formFunc = formFunc;
}
override canApply({ pokemon }: AbAttrBaseParams): boolean {
return this.formFunc(pokemon) !== pokemon.formIndex;
}
override apply({ pokemon, simulated }: AbAttrBaseParams): void {
if (!simulated) {
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeAbilityTrigger, false);
}
}
}
export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
private damageRatio: number; private damageRatio: number;
@ -7296,6 +7316,7 @@ export function initAbilities() {
(pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }), (pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }),
(pokemon) => toDmgValue(pokemon.getMaxHp() / 8)) (pokemon) => toDmgValue(pokemon.getMaxHp() / 8))
.attr(PostBattleInitFormChangeAbAttr, () => 0) .attr(PostBattleInitFormChangeAbAttr, () => 0)
.attr(PostFaintFormChangeAbAttr, () => 0)
.uncopiable() .uncopiable()
.unreplaceable() .unreplaceable()
.unsuppressable() .unsuppressable()
@ -7304,6 +7325,7 @@ export function initAbilities() {
new Ability(AbilityId.BATTLE_BOND, 7) new Ability(AbilityId.BATTLE_BOND, 7)
.attr(PostVictoryFormChangeAbAttr, () => 2) .attr(PostVictoryFormChangeAbAttr, () => 2)
.attr(PostBattleInitFormChangeAbAttr, () => 1) .attr(PostBattleInitFormChangeAbAttr, () => 1)
.attr(PostFaintFormChangeAbAttr, () => 1)
.attr(NoFusionAbilityAbAttr) .attr(NoFusionAbilityAbAttr)
.uncopiable() .uncopiable()
.unreplaceable() .unreplaceable()
@ -7315,6 +7337,7 @@ export function initAbilities() {
.conditionalAttr(p => p.formIndex === 4 || p.formIndex === 5, PostBattleInitFormChangeAbAttr, p => p.formIndex - 2) .conditionalAttr(p => p.formIndex === 4 || p.formIndex === 5, PostBattleInitFormChangeAbAttr, p => p.formIndex - 2)
.conditionalAttr(p => p.getHpRatio() <= 0.5 && (p.formIndex === 2 || p.formIndex === 3), PostSummonFormChangeAbAttr, p => p.formIndex + 2) .conditionalAttr(p => p.getHpRatio() <= 0.5 && (p.formIndex === 2 || p.formIndex === 3), PostSummonFormChangeAbAttr, p => p.formIndex + 2)
.conditionalAttr(p => p.getHpRatio() <= 0.5 && (p.formIndex === 2 || p.formIndex === 3), PostTurnFormChangeAbAttr, p => p.formIndex + 2) .conditionalAttr(p => p.getHpRatio() <= 0.5 && (p.formIndex === 2 || p.formIndex === 3), PostTurnFormChangeAbAttr, p => p.formIndex + 2)
.conditionalAttr(p => p.formIndex === 4 || p.formIndex === 5, PostFaintFormChangeAbAttr, p => p.formIndex - 2)
.attr(NoFusionAbilityAbAttr) .attr(NoFusionAbilityAbAttr)
.uncopiable() .uncopiable()
.unreplaceable() .unreplaceable()

View File

@ -165,7 +165,7 @@ describe("Abilities - Disguise", () => {
expect(mimikyu.formIndex).toBe(disguisedForm); expect(mimikyu.formIndex).toBe(disguisedForm);
}); });
it("reverts to Disguised form on biome change when fainted", async () => { it("reverts to Disguised form when fainted", async () => {
game.override game.override
.startingWave(10) .startingWave(10)
.starterSpecies(0) .starterSpecies(0)
@ -181,10 +181,6 @@ describe("Abilities - Disguise", () => {
game.move.select(MoveId.SPLASH); game.move.select(MoveId.SPLASH);
await game.killPokemon(mimikyu1); await game.killPokemon(mimikyu1);
game.doSelectPartyPokemon(1);
await game.toNextTurn();
game.move.select(MoveId.SPLASH);
await game.doKillOpponents();
await game.phaseInterceptor.to("QuietFormChangePhase"); await game.phaseInterceptor.to("QuietFormChangePhase");
expect(mimikyu1.formIndex).toBe(disguisedForm); expect(mimikyu1.formIndex).toBe(disguisedForm);