diff --git a/src/battle-phases.ts b/src/battle-phases.ts index eb34e9c06..d32b9bf0d 100644 --- a/src/battle-phases.ts +++ b/src/battle-phases.ts @@ -286,7 +286,7 @@ export abstract class FieldPhase extends BattlePhase { } executeForAll(func: PokemonFunc): void { - const field = this.scene.getField().filter(p => p?.isActive()); + const field = this.scene.getField().filter(p => p?.summonData && p.isActive()); field.forEach(pokemon => func(pokemon)); } } @@ -2389,6 +2389,14 @@ export class DamagePhase extends PokemonPhase { this.scene.addEnemyModifier(getModifierType(modifierTypes.MINI_BLACK_HOLE).newModifier(pokemon) as PersistentModifier, false, true); pokemon.generateAndPopulateMoveset(1); this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + this.scene.currentBattle.double = true; + const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()); + if (availablePartyMembers.length > 1) { + this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, true)); + if (!availablePartyMembers[1].isOnField()) + this.scene.pushPhase(new SummonPhase(this.scene, 1)); + } + super.end(); }, null, true); return; diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index f3858a226..2e8389014 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -760,8 +760,8 @@ export abstract class BattleAnim { if (isUser && target === user) continue; const sprites = spriteCache[isUser ? AnimFrameTarget.USER : AnimFrameTarget.TARGET]; + const spriteSource = isUser ? userSprite : targetSprite; if ((isUser ? u : t) === sprites.length) { - const spriteSource = isUser ? userSprite : targetSprite; let sprite: Phaser.GameObjects.Sprite; sprite = scene.addFieldSprite(0, 0, spriteSource.texture, spriteSource.frame.name); sprite.setPipeline(scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: true }); @@ -772,12 +772,12 @@ export abstract class BattleAnim { } const spriteIndex = isUser ? u++ : t++; - const pokemonSprite = sprites[spriteIndex]; + const pokemonSprite = sprites[spriteIndex]; const graphicFrameData = frameData.get(frame.target).get(spriteIndex); - pokemonSprite.setPosition(graphicFrameData.x, graphicFrameData.y); + pokemonSprite.setPosition(graphicFrameData.x, graphicFrameData.y - ((spriteSource.height / 2) * (spriteSource.parentContainer.scale - 1))); pokemonSprite.setAngle(graphicFrameData.angle); - pokemonSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY); + pokemonSprite.setScale(graphicFrameData.scaleX * spriteSource.parentContainer.scale, graphicFrameData.scaleY * spriteSource.parentContainer.scale); pokemonSprite.setData('locked', frame.locked); diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index c0fdc71bf..d5a6f90a5 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -257,7 +257,7 @@ export const battleSpecDialogue = { $Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain. $Until now you have yet to succeed, but I sense a different presence in you this time.\n $You are the only one here, though it is as if there is… another. - $Will you finally prove a formidable challenge to me?\nThe challenge I have longed for for millenia? + $Will you finally prove a formidable challenge to me?\nThe challenge I have longed for for millennia? $We begin.`, firstStageWin: `I see. The presence I felt was indeed real.\nIt appears I no longer need to hold back. $Do not disappoint me.`, diff --git a/src/form-change-phase.ts b/src/form-change-phase.ts index 414aba577..439ffa622 100644 --- a/src/form-change-phase.ts +++ b/src/form-change-phase.ts @@ -182,8 +182,79 @@ export class QuietFormChangePhase extends BattlePhase { return this.end(); const preName = this.pokemon.name; - this.pokemon.changeForm(this.formChange).then(() => { - this.scene.ui.showText(getSpeciesFormChangeMessage(this.pokemon, this.formChange, preName), null, () => this.end(), Utils.fixedInt(1500)); + + const getPokemonSprite = () => { + const sprite = this.scene.addFieldSprite(this.pokemon.x + this.pokemon.getSprite().x, this.pokemon.y + this.pokemon.getSprite().y, `pkmn__sub`); + sprite.setOrigin(0.5, 1); + sprite.play(this.pokemon.getSpriteKey()).stop(); + sprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false }); + [ 'spriteColors', 'fusionSpriteColors' ].map(k => { + if (this.pokemon.summonData?.speciesForm) + k += 'Base'; + sprite.pipelineData[k] = this.pokemon.getSprite().pipelineData[k]; + }); + this.scene.field.add(sprite); + return sprite; + } + + const [ pokemonTintSprite, pokemonFormTintSprite ] = [ getPokemonSprite(), getPokemonSprite() ]; + + this.pokemon.getSprite().on('animationupdate', (_anim, frame) => { + if (frame.textureKey === pokemonTintSprite.texture.key) + pokemonTintSprite.setFrame(frame.textureFrame); + else + pokemonFormTintSprite.setFrame(frame.textureFrame); + }); + + pokemonTintSprite.setAlpha(0); + pokemonTintSprite.setTintFill(0xFFFFFF); + pokemonFormTintSprite.setVisible(false); + pokemonFormTintSprite.setTintFill(0xFFFFFF); + + this.scene.playSound('PRSFX- Transform'); + + this.scene.tweens.add({ + targets: pokemonTintSprite, + alpha: 1, + duration: 1000, + ease: 'Cubic.easeIn', + onComplete: () => { + this.pokemon.setVisible(false); + this.pokemon.changeForm(this.formChange).then(() => { + pokemonFormTintSprite.setScale(0.01); + pokemonFormTintSprite.play(this.pokemon.getSpriteKey()).stop(); + pokemonFormTintSprite.setVisible(true); + this.scene.tweens.add({ + targets: pokemonTintSprite, + delay: 250, + scale: 0.01, + ease: 'Cubic.easeInOut', + duration: 500, + onComplete: () => pokemonTintSprite.destroy() + }); + this.scene.tweens.add({ + targets: pokemonFormTintSprite, + delay: 250, + scale: 1, + ease: 'Cubic.easeInOut', + duration: 500, + onComplete: () => { + this.pokemon.setVisible(true); + this.scene.tweens.add({ + targets: pokemonFormTintSprite, + delay: 250, + alpha: 0, + ease: 'Cubic.easeOut', + duration: 1000, + onComplete: () => { + pokemonTintSprite.setVisible(false); + this.scene.ui.showText(getSpeciesFormChangeMessage(this.pokemon, this.formChange, preName), null, () => this.end(), Utils.fixedInt(1500)); + } + }); + } + }); + }); + } }); } diff --git a/src/pipelines/sprite.ts b/src/pipelines/sprite.ts index 07a14ec57..50cefcab8 100644 --- a/src/pipelines/sprite.ts +++ b/src/pipelines/sprite.ts @@ -212,15 +212,18 @@ export default class SpritePipeline extends FieldSpritePipeline { const spriteColors = (ignoreOverride && data['spriteColorsBase']) || data['spriteColors'] || [] as number[][]; const fusionSpriteColors = (ignoreOverride && data['fusionSpriteColorsBase']) || data['fusionSpriteColors'] || [] as number[][]; - const position = sprite.parentContainer instanceof Pokemon || sprite.parentContainer instanceof Trainer + const isEntityObj = sprite.parentContainer instanceof Pokemon || sprite.parentContainer instanceof Trainer; + const position = isEntityObj ? [ sprite.parentContainer.x, sprite.parentContainer.y ] : [ sprite.x, sprite.y ]; position[0] += -(sprite.width - sprite.frame.width) / 2 + sprite.frame.x; + if (sprite.originY === 0.5) + position[1] += (sprite.height / 2) * ((isEntityObj ? sprite.parentContainer : sprite).scale - 1); this.set1i('hasShadow', hasShadow ? 1 : 0); this.set1i('yCenter', sprite.originY === 0.5 ? 1 : 0); this.set2f('relPosition', position[0], position[1]); this.set2f('size', sprite.frame.width, sprite.height); - this.set1f('yOffset', sprite.height - sprite.frame.height); + this.set1f('yOffset', sprite.height - sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale)); this.set4fv('tone', tone); const emptyColors = [ 0, 0, 0, 0 ]; const flatSpriteColors: integer[] = []; @@ -243,13 +246,14 @@ export default class SpritePipeline extends FieldSpritePipeline { const hasShadow = sprite.pipelineData['hasShadow'] as boolean; if (hasShadow) { - const baseY = (sprite.parentContainer instanceof Pokemon || sprite.parentContainer instanceof Trainer + const isEntityObj = sprite.parentContainer instanceof Pokemon || sprite.parentContainer instanceof Trainer; + const baseY = (isEntityObj ? sprite.parentContainer.y - : sprite.y + sprite.height / 2) * 6; + : sprite.y + sprite.height) * 6; const bottomPadding = Math.ceil(sprite.height * 0.05) * 6; const yDelta = (baseY - y1) / 6; y2 = y1 = baseY + bottomPadding; - const pixelHeight = (v1 - v0) / sprite.frame.height; + const pixelHeight = ((v1 - v0) / (sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale))); v1 += (yDelta + bottomPadding / 6) * pixelHeight; } diff --git a/src/pokemon.ts b/src/pokemon.ts index 8375d3300..688159cc8 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -207,6 +207,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: !!hasShadow }); return ret; }; + + this.setScale(this.getSpriteScale()); const sprite = getSprite(true); const tintSprite = getSprite(); @@ -396,6 +398,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { : this.maskSprite; } + getSpriteScale(): number { + return 1; + } + initShinySparkle(): void { const shinySparkle = this.scene.addFieldSprite(0, 0, 'shiny'); shinySparkle.setVisible(false); @@ -1250,6 +1256,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (this.abilityIndex >= abilityCount) // Shouldn't happen this.abilityIndex = abilityCount - 1; this.scene.gameData.setPokemonSeen(this, true); + this.setScale(this.getSpriteScale()); this.loadAssets().then(() => { this.calculateStats(); this.scene.updateModifiers(this.isPlayer(), true); @@ -1559,7 +1566,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.maskSprite = this.getTintSprite(); this.maskSprite.setVisible(true); this.maskSprite.setPosition(this.x * 6, this.y * 6); - this.maskSprite.setScale(6); + this.maskSprite.setScale(6 * this.getSpriteScale()); this.maskEnabled = true; } } @@ -1568,7 +1575,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (this.maskEnabled) { this.maskSprite.setVisible(false); this.maskSprite.setPosition(0, 0); - this.maskSprite.setScale(1); + this.maskSprite.setScale(this.getSpriteScale()); this.maskSprite = null; this.maskEnabled = false; }