[P1] Transform and Imposter will now fail when either Pokemon is fused (#4824)

* Transform and Imposter will now fail when either Pokemon is fused

* Prevent Ditto from being randomly generated as part of a fusion
This commit is contained in:
NightKev 2024-11-09 21:39:05 -08:00 committed by GitHub
parent b3a94e6a6b
commit 2968059814
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 50 additions and 22 deletions

View File

@ -2463,12 +2463,15 @@ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr {
} }
} }
/**
* Used by Imposter
*/
export class PostSummonTransformAbAttr extends PostSummonAbAttr { export class PostSummonTransformAbAttr extends PostSummonAbAttr {
constructor() { constructor() {
super(true); super(true);
} }
async applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): Promise<boolean> { async applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): Promise<boolean> {
const targets = pokemon.getOpponents(); const targets = pokemon.getOpponents();
if (simulated || !targets.length) { if (simulated || !targets.length) {
return simulated; return simulated;
@ -2477,17 +2480,31 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
let target: Pokemon; let target: Pokemon;
if (targets.length > 1) { if (targets.length > 1) {
pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets), pokemon.scene.currentBattle.waveIndex); pokemon.scene.executeWithSeedOffset(() => {
// in a double battle, if one of the opposing pokemon is fused the other one will be chosen
// if both are fused, then Imposter will fail below
if (targets[0].fusionSpecies) {
target = targets[1];
return;
} else if (targets[1].fusionSpecies) {
target = targets[0];
return;
}
target = Utils.randSeedItem(targets);
}, pokemon.scene.currentBattle.waveIndex);
} else { } else {
target = targets[0]; target = targets[0];
} }
target = target!; target = target!;
// transforming from or into fusion pokemon causes various problems (including crashes and save corruption)
if (target.fusionSpecies || pokemon.fusionSpecies) {
return false;
}
pokemon.summonData.speciesForm = target.getSpeciesForm(); pokemon.summonData.speciesForm = target.getSpeciesForm();
pokemon.summonData.fusionSpeciesForm = target.getFusionSpeciesForm();
pokemon.summonData.ability = target.getAbility().id; pokemon.summonData.ability = target.getAbility().id;
pokemon.summonData.gender = target.getGender(); pokemon.summonData.gender = target.getGender();
pokemon.summonData.fusionGender = target.getFusionGender();
// Copy all stats (except HP) // Copy all stats (except HP)
for (const s of EFFECTIVE_STATS) { for (const s of EFFECTIVE_STATS) {

View File

@ -6995,6 +6995,9 @@ export class SuppressAbilitiesIfActedAttr extends MoveEffectAttr {
} }
} }
/**
* Used by Transform
*/
export class TransformAttr extends MoveEffectAttr { export class TransformAttr extends MoveEffectAttr {
async apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> { async apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
if (!super.apply(user, target, move, args)) { if (!super.apply(user, target, move, args)) {
@ -7003,10 +7006,8 @@ export class TransformAttr extends MoveEffectAttr {
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];
user.summonData.speciesForm = target.getSpeciesForm(); user.summonData.speciesForm = target.getSpeciesForm();
user.summonData.fusionSpeciesForm = target.getFusionSpeciesForm();
user.summonData.ability = target.getAbility().id; user.summonData.ability = target.getAbility().id;
user.summonData.gender = target.getGender(); user.summonData.gender = target.getGender();
user.summonData.fusionGender = target.getFusionGender();
// Power Trick's effect will not preserved after using Transform // Power Trick's effect will not preserved after using Transform
user.removeTag(BattlerTagType.POWER_TRICK); user.removeTag(BattlerTagType.POWER_TRICK);
@ -8077,7 +8078,8 @@ export function initMoves() {
.ignoresVirtual(), .ignoresVirtual(),
new StatusMove(Moves.TRANSFORM, Type.NORMAL, -1, 10, -1, 0, 1) new StatusMove(Moves.TRANSFORM, Type.NORMAL, -1, 10, -1, 0, 1)
.attr(TransformAttr) .attr(TransformAttr)
.condition((user, target, move) => !target.getTag(BattlerTagType.SUBSTITUTE)) // transforming from or into fusion pokemon causes various problems (such as crashes)
.condition((user, target, move) => !target.getTag(BattlerTagType.SUBSTITUTE) && !user.fusionSpecies && !target.fusionSpecies)
.ignoresProtect(), .ignoresProtect(),
new AttackMove(Moves.BUBBLE, Type.WATER, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1) new AttackMove(Moves.BUBBLE, Type.WATER, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1)
.attr(StatStageChangeAttr, [ Stat.SPD ], -1) .attr(StatStageChangeAttr, [ Stat.SPD ], -1)

View File

@ -888,17 +888,24 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
getCompatibleFusionSpeciesFilter(): PokemonSpeciesFilter { getCompatibleFusionSpeciesFilter(): PokemonSpeciesFilter {
const hasEvolution = pokemonEvolutions.hasOwnProperty(this.speciesId); const hasEvolution = pokemonEvolutions.hasOwnProperty(this.speciesId);
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(this.speciesId); const hasPrevolution = pokemonPrevolutions.hasOwnProperty(this.speciesId);
const pseudoLegendary = this.subLegendary; const subLegendary = this.subLegendary;
const legendary = this.legendary; const legendary = this.legendary;
const mythical = this.mythical; const mythical = this.mythical;
return species => { return species => {
return (pseudoLegendary || legendary || mythical || return (
(pokemonEvolutions.hasOwnProperty(species.speciesId) === hasEvolution subLegendary
&& pokemonPrevolutions.hasOwnProperty(species.speciesId) === hasPrevolution)) || legendary
&& species.subLegendary === pseudoLegendary || mythical
|| (
pokemonEvolutions.hasOwnProperty(species.speciesId) === hasEvolution
&& pokemonPrevolutions.hasOwnProperty(species.speciesId) === hasPrevolution
)
)
&& species.subLegendary === subLegendary
&& species.legendary === legendary && species.legendary === legendary
&& species.mythical === mythical && species.mythical === mythical
&& (this.isTrainerForbidden() || !species.isTrainerForbidden()); && (this.isTrainerForbidden() || !species.isTrainerForbidden())
&& species.speciesId !== Species.DITTO;
}; };
} }

View File

@ -2030,15 +2030,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value); const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value);
const randAbilityIndex = Utils.randSeedInt(2); const randAbilityIndex = Utils.randSeedInt(2);
const filter = !forStarter ? this.species.getCompatibleFusionSpeciesFilter() const filter = !forStarter ?
: species => { this.species.getCompatibleFusionSpeciesFilter()
: (species: PokemonSpecies) => {
return pokemonEvolutions.hasOwnProperty(species.speciesId) return pokemonEvolutions.hasOwnProperty(species.speciesId)
&& !pokemonPrevolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId)
&& !species.pseudoLegendary && !species.subLegendary
&& !species.legendary && !species.legendary
&& !species.mythical && !species.mythical
&& !species.isTrainerForbidden() && !species.isTrainerForbidden()
&& species.speciesId !== this.species.speciesId; && species.speciesId !== this.species.speciesId
&& species.speciesId !== Species.DITTO;
}; };
let fusionOverride: PokemonSpecies | undefined = undefined; let fusionOverride: PokemonSpecies | undefined = undefined;