mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-02-15 16:57:10 +00:00
* Implement Substitute Squashed commit from working branch * Fix integration test imports * Use Override Helper utils + Fix Baton Pass test * Update src/test/moves/substitute.test.ts Co-authored-by: Adrian T. <68144167+torranx@users.noreply.github.com> * Fix test imports + nits * Document RemoveAllSubstitutesAttr * Fix some strict-null issues * more strict-null fixes * Fix baton pass test * Reorganized Substitute translation keys * Added checks for substitute in contact logic * Clean up Unseen Fist contact logic * Remove misleading comment in Download attr * RIP phases.ts * Fix imports post-phase migration * Rewrite `move.canIgnoreSubstitute` to `move.hitsSubstitute` * Also fixed interactions with Shell Trap and Beak Blast * Removed some leftover `canIgnoreSubstitute`s * fix issues after beta merge * Status move effectiveness now accounts for substitute * More edge case tests (Counter test failing) * Fix Counter + Trap edge cases + add Fail messagesd * Fix leftover nit * Resolve leftover test issues * Fix Sub offset carrying over to Trainer fights * Hide substitute sprite during catch attempts * Make substitutes baton-passable again * Remove placeholder locale keys and SPLASH_ONLY * Fix imports and other nits Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * ESLint * Fix imports * Fix incorrect `resetSprite` timing * Fix substitute disappearing on hit (maybe?) * More animation fixes (mostly for Roar) --------- Co-authored-by: Adrian T. <68144167+torranx@users.noreply.github.com> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
238 lines
6.2 KiB
TypeScript
238 lines
6.2 KiB
TypeScript
import BattleScene from "#app/battle-scene";
|
|
import { SubstituteTag } from "#app/data/battler-tags";
|
|
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
|
import Pokemon from "#app/field/pokemon";
|
|
import { BattlePhase } from "#app/phases/battle-phase";
|
|
|
|
|
|
|
|
export class PokemonAnimPhase extends BattlePhase {
|
|
/** The type of animation to play in this phase */
|
|
private key: PokemonAnimType;
|
|
/** The Pokemon to which this animation applies */
|
|
private pokemon: Pokemon;
|
|
/** Any other field sprites affected by this animation */
|
|
private fieldAssets: Phaser.GameObjects.Sprite[];
|
|
|
|
constructor(scene: BattleScene, key: PokemonAnimType, pokemon: Pokemon, fieldAssets?: Phaser.GameObjects.Sprite[]) {
|
|
super(scene);
|
|
|
|
this.key = key;
|
|
this.pokemon = pokemon;
|
|
this.fieldAssets = fieldAssets ?? [];
|
|
}
|
|
|
|
start(): void {
|
|
super.start();
|
|
|
|
switch (this.key) {
|
|
case PokemonAnimType.SUBSTITUTE_ADD:
|
|
this.doSubstituteAddAnim();
|
|
break;
|
|
case PokemonAnimType.SUBSTITUTE_PRE_MOVE:
|
|
this.doSubstitutePreMoveAnim();
|
|
break;
|
|
case PokemonAnimType.SUBSTITUTE_POST_MOVE:
|
|
this.doSubstitutePostMoveAnim();
|
|
break;
|
|
case PokemonAnimType.SUBSTITUTE_REMOVE:
|
|
this.doSubstituteRemoveAnim();
|
|
break;
|
|
default:
|
|
this.end();
|
|
}
|
|
}
|
|
|
|
doSubstituteAddAnim(): void {
|
|
const substitute = this.pokemon.getTag(SubstituteTag);
|
|
if (substitute === null) {
|
|
return this.end();
|
|
}
|
|
|
|
const getSprite = () => {
|
|
const sprite = this.scene.addFieldSprite(
|
|
this.pokemon.x + this.pokemon.getSprite().x,
|
|
this.pokemon.y + this.pokemon.getSprite().y,
|
|
`pkmn${this.pokemon.isPlayer() ? "__back": ""}__sub`
|
|
);
|
|
sprite.setOrigin(0.5, 1);
|
|
this.scene.field.add(sprite);
|
|
return sprite;
|
|
};
|
|
|
|
const [ subSprite, subTintSprite ] = [ getSprite(), getSprite() ];
|
|
const subScale = this.pokemon.getSpriteScale() * (this.pokemon.isPlayer() ? 0.5 : 1);
|
|
|
|
subSprite.setVisible(false);
|
|
subSprite.setScale(subScale);
|
|
subTintSprite.setTintFill(0xFFFFFF);
|
|
subTintSprite.setScale(0.01);
|
|
|
|
if (this.pokemon.isPlayer()) {
|
|
this.scene.field.bringToTop(this.pokemon);
|
|
}
|
|
|
|
this.scene.playSound("PRSFX- Transform");
|
|
|
|
this.scene.tweens.add({
|
|
targets: this.pokemon,
|
|
duration: 500,
|
|
x: this.pokemon.x + this.pokemon.getSubstituteOffset()[0],
|
|
y: this.pokemon.y + this.pokemon.getSubstituteOffset()[1],
|
|
alpha: 0.5,
|
|
ease: "Sine.easeIn"
|
|
});
|
|
|
|
this.scene.tweens.add({
|
|
targets: subTintSprite,
|
|
delay: 250,
|
|
scale: subScale,
|
|
ease: "Cubic.easeInOut",
|
|
duration: 500,
|
|
onComplete: () => {
|
|
subSprite.setVisible(true);
|
|
this.pokemon.scene.tweens.add({
|
|
targets: subTintSprite,
|
|
delay: 250,
|
|
alpha: 0,
|
|
ease: "Cubic.easeOut",
|
|
duration: 1000,
|
|
onComplete: () => {
|
|
subTintSprite.destroy();
|
|
substitute.sprite = subSprite;
|
|
this.end();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
doSubstitutePreMoveAnim(): void {
|
|
if (this.fieldAssets.length !== 1) {
|
|
return this.end();
|
|
}
|
|
|
|
const subSprite = this.fieldAssets[0];
|
|
if (subSprite === undefined) {
|
|
return this.end();
|
|
}
|
|
|
|
this.scene.tweens.add({
|
|
targets: subSprite,
|
|
alpha: 0,
|
|
ease: "Sine.easeInOut",
|
|
duration: 500
|
|
});
|
|
|
|
this.scene.tweens.add({
|
|
targets: this.pokemon,
|
|
x: subSprite.x,
|
|
y: subSprite.y,
|
|
alpha: 1,
|
|
ease: "Sine.easeInOut",
|
|
delay: 250,
|
|
duration: 500,
|
|
onComplete: () => this.end()
|
|
});
|
|
}
|
|
|
|
doSubstitutePostMoveAnim(): void {
|
|
if (this.fieldAssets.length !== 1) {
|
|
return this.end();
|
|
}
|
|
|
|
const subSprite = this.fieldAssets[0];
|
|
if (subSprite === undefined) {
|
|
return this.end();
|
|
}
|
|
|
|
this.scene.tweens.add({
|
|
targets: this.pokemon,
|
|
x: subSprite.x + this.pokemon.getSubstituteOffset()[0],
|
|
y: subSprite.y + this.pokemon.getSubstituteOffset()[1],
|
|
alpha: 0.5,
|
|
ease: "Sine.easeInOut",
|
|
duration: 500
|
|
});
|
|
|
|
this.scene.tweens.add({
|
|
targets: subSprite,
|
|
alpha: 1,
|
|
ease: "Sine.easeInOut",
|
|
delay: 250,
|
|
duration: 500,
|
|
onComplete: () => this.end()
|
|
});
|
|
}
|
|
|
|
doSubstituteRemoveAnim(): void {
|
|
if (this.fieldAssets.length !== 1) {
|
|
return this.end();
|
|
}
|
|
|
|
const subSprite = this.fieldAssets[0];
|
|
if (subSprite === undefined) {
|
|
return this.end();
|
|
}
|
|
|
|
const getSprite = () => {
|
|
const sprite = this.scene.addFieldSprite(
|
|
subSprite.x,
|
|
subSprite.y,
|
|
`pkmn${this.pokemon.isPlayer() ? "__back": ""}__sub`
|
|
);
|
|
sprite.setOrigin(0.5, 1);
|
|
this.scene.field.add(sprite);
|
|
return sprite;
|
|
};
|
|
|
|
const subTintSprite = getSprite();
|
|
const subScale = this.pokemon.getSpriteScale() * (this.pokemon.isPlayer() ? 0.5 : 1);
|
|
subTintSprite.setAlpha(0);
|
|
subTintSprite.setTintFill(0xFFFFFF);
|
|
subTintSprite.setScale(subScale);
|
|
|
|
this.scene.tweens.add({
|
|
targets: subTintSprite,
|
|
alpha: 1,
|
|
ease: "Sine.easeInOut",
|
|
duration: 500,
|
|
onComplete: () => {
|
|
subSprite.destroy();
|
|
const flashTimer = this.scene.time.addEvent({
|
|
delay: 100,
|
|
repeat: 7,
|
|
startAt: 200,
|
|
callback: () => {
|
|
this.scene.playSound("PRSFX- Substitute2.wav");
|
|
|
|
subTintSprite.setVisible(flashTimer.repeatCount % 2 === 0);
|
|
if (!flashTimer.repeatCount) {
|
|
this.scene.tweens.add({
|
|
targets: subTintSprite,
|
|
scale: 0.01,
|
|
ease: "Sine.cubicEaseIn",
|
|
duration: 500
|
|
});
|
|
|
|
this.scene.tweens.add({
|
|
targets: this.pokemon,
|
|
x: this.pokemon.x - this.pokemon.getSubstituteOffset()[0],
|
|
y: this.pokemon.y - this.pokemon.getSubstituteOffset()[1],
|
|
alpha: 1,
|
|
ease: "Sine.easeInOut",
|
|
delay: 250,
|
|
duration: 500,
|
|
onComplete: () => {
|
|
subTintSprite.destroy();
|
|
this.end();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|