From 4c29854c23924ba81ae9595b3a0c09cc1227cc52 Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Fri, 3 May 2024 00:15:31 -0500 Subject: [PATCH] Fix Form Changes with Secondary Fusion Component Allows form changes when you have a Pokemon chosen as the second component of a fusion. i.e. Charizard/Snorlax can still be Dynamaxed with a Max Mushroom. This also allows these items to spawn where they wouldn't previously. --- src/battle-scene.ts | 39 +++++++++++++++---------- src/data/pokemon-forms.ts | 55 ++++++++++++++++++++++------------- src/field/pokemon.ts | 9 +++++- src/modifier/modifier-type.ts | 9 +++++- 4 files changed, 74 insertions(+), 38 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index cbf363f689a..a0fe6950b6b 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -2134,23 +2134,30 @@ export default class BattleScene extends SceneBase { } triggerPokemonFormChange(pokemon: Pokemon, formChangeTriggerType: { new(...args: any[]): SpeciesFormChangeTrigger }, delayed: boolean = false, modal: boolean = false): boolean { - if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId)) { - const matchingFormChange = pokemonFormChanges[pokemon.species.speciesId].find(fc => fc.findTrigger(formChangeTriggerType) && fc.canChange(pokemon)); - if (matchingFormChange) { - let phase: Phase; - if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet) - phase = new FormChangePhase(this, pokemon, matchingFormChange, modal); - else - phase = new QuietFormChangePhase(this, pokemon, matchingFormChange); - if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet && modal) - this.overridePhase(phase); - else if (delayed) - this.pushPhase(phase); - else - this.unshiftPhase(phase); - return true; + const speciesIds = [pokemon.species.speciesId]; + if (pokemon.isFusion()) + speciesIds.push(pokemon.fusionSpecies.speciesId) + + speciesIds.forEach(speciesId => + { + if (pokemonFormChanges.hasOwnProperty(speciesId)) { + const matchingFormChange = pokemonFormChanges[speciesId].find(fc => fc.findTrigger(formChangeTriggerType) && fc.canChange(pokemon)); + if (matchingFormChange) { + let phase: Phase; + if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet) + phase = new FormChangePhase(this, pokemon, matchingFormChange, modal); + else + phase = new QuietFormChangePhase(this, pokemon, matchingFormChange); + if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet && modal) + this.overridePhase(phase); + else if (delayed) + this.pushPhase(phase); + else + this.unshiftPhase(phase); + return true; + } } - } + }); return false; } diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 87094af2028..55e21ae928b 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -7,6 +7,7 @@ import { Species } from "./enums/species"; import { StatusEffect } from "./status-effect"; import { MoveCategory, allMoves } from "./move"; import { Abilities } from "./enums/abilities"; +import { PokemonSpecies } from "pokenode-ts"; export enum FormChangeItem { NONE, @@ -105,29 +106,43 @@ export class SpeciesFormChange { this.conditions = conditions; } - canChange(pokemon: Pokemon): boolean { - if (pokemon.species.speciesId !== this.speciesId) - return false; + canChange(pokemon: Pokemon): boolean { + const speciesArray = [pokemon.species]; + const formIndexes = [pokemon.formIndex]; - if (!pokemon.species.forms.length) - return false; + if (pokemon.isFusion()) { + speciesArray.push(pokemon.fusionSpecies); + formIndexes.push(pokemon.fusionFormIndex); + } - const formKeys = pokemon.species.forms.map(f => f.formKey); - if (formKeys[pokemon.formIndex] !== this.preFormKey) - return false; - - if (formKeys[pokemon.formIndex] === this.formKey) - return false; - - for (let condition of this.conditions) { - if (!condition.predicate(pokemon)) - return false; + const formMatch = [true, true]; + for (let i = 0; i < speciesArray.length; ++i) { + const species = speciesArray[i]; + const formIndex = formIndexes[i]; + + if (species.speciesId !== this.speciesId) + formMatch[i] = false; + + if (!species.forms.length) + formMatch[i] = false; + + const formKeys = species.forms.map(f => f.formKey); + if (formKeys[formIndex] !== this.preFormKey) + formMatch[i] = false; + + if (formKeys[formIndex] === this.formKey) + formMatch[i] = false; + + for (let condition of this.conditions) { + if (!condition.predicate(pokemon)) + formMatch[i] = false; + } + + if (!this.trigger.canChange(pokemon)) + formMatch[i] = false; } - if (!this.trigger.canChange(pokemon)) - return false; - - return true; + return formMatch.some(x => x); } findTrigger(triggerType: { new(...args: any[]): SpeciesFormChangeTrigger }): SpeciesFormChangeTrigger { @@ -304,7 +319,7 @@ export function getSpeciesFormChangeMessage(pokemon: Pokemon, formChange: Specie const isMega = formChange.formKey.indexOf(SpeciesFormKey.MEGA) > -1; const isGmax = formChange.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1; const isEmax = formChange.formKey.indexOf('eternamax') > -1; - const isRevert = !isMega && formChange.formKey === pokemon.species.forms[0].formKey; + const isRevert = !isMega && ((!!pokemon.species.forms.length && formChange.formKey === pokemon.species.forms[0].formKey) || (pokemon.isFusion() && pokemon.fusionSpecies.forms[0].formKey)); const prefix = !pokemon.isPlayer() ? pokemon.hasTrainer() ? 'Foe ' : 'Wild ' : 'Your '; if (isMega) return `${prefix}${preName} mega-evolved\ninto ${pokemon.name}!`; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 7720d741b20..2d6cf6fc9fe 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2507,8 +2507,15 @@ export class PlayerPokemon extends Pokemon { } changeForm(formChange: SpeciesFormChange): Promise { + const matchesBase = this.species.speciesId == formChange.speciesId; + return new Promise(resolve => { - this.formIndex = Math.max(this.species.forms.findIndex(f => f.formKey === formChange.formKey), 0); + const newFormIndex = Math.max((matchesBase ? this.species : this.fusionSpecies).forms.findIndex(f => f.formKey === formChange.formKey), 0); + if (matchesBase) + this.formIndex = newFormIndex; + else + this.fusionFormIndex = newFormIndex; + this.generateName(); const abilityCount = this.getSpeciesForm().getAbilityCount(); if (this.abilityIndex >= abilityCount) // Shouldn't happen diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 4229b8be3b7..6fe8bac242a 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -574,6 +574,10 @@ export class FormChangeItemModifierType extends PokemonModifierType implements G && (fc.trigger as SpeciesFormChangeItemTrigger).item === this.formChangeItem)) return null; + if (pokemon.isFusion() && pokemonFormChanges.hasOwnProperty(pokemon.fusionSpecies.speciesId) && !!pokemonFormChanges[pokemon.fusionSpecies.speciesId].find(fc => fc.trigger.hasTriggerType(SpeciesFormChangeItemTrigger) + && (fc.trigger as SpeciesFormChangeItemTrigger).item === this.formChangeItem)) + return null; + return PartyUiHandler.NoEffectMessage; }, FormChangeItem[formChangeItem].toLowerCase()); @@ -686,7 +690,10 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator { return new FormChangeItemModifierType(pregenArgs[0] as FormChangeItem); const formChangeItemPool = party.filter(p => pokemonFormChanges.hasOwnProperty(p.species.speciesId)).map(p => { - const formChanges = pokemonFormChanges[p.species.speciesId]; + let formChanges = pokemonFormChanges[p.species.speciesId]; + if(p.isFusion()) + formChanges = formChanges.concat(pokemonFormChanges[p.fusionSpecies.speciesId]); + return formChanges.filter(fc => ((fc.formKey.indexOf(SpeciesFormKey.MEGA) === -1 && fc.formKey.indexOf(SpeciesFormKey.PRIMAL) === -1) || party[0].scene.getModifiers(Modifiers.MegaEvolutionAccessModifier).length) && ((fc.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) === -1 && fc.formKey.indexOf(SpeciesFormKey.ETERNAMAX) === -1) || party[0].scene.getModifiers(Modifiers.GigantamaxAccessModifier).length)) .map(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)