Merge branch 'beta' into feat/export-settings

This commit is contained in:
NightKev 2024-11-27 23:29:12 -08:00 committed by GitHub
commit 7c57ccf42e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 216 additions and 86 deletions

View File

@ -123,6 +123,7 @@ Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to
- Involuntary-Twitch
- selstar
- koda_want_to_sleep
- thedreadedden
### 🎨 Move Animations
- Pokémon Reborn

87
package-lock.json generated
View File

@ -16,6 +16,7 @@
"i18next-http-backend": "^2.6.1",
"i18next-korean-postposition-processor": "^1.0.0",
"json-stable-stringify": "^1.1.0",
"jszip": "^3.10.1",
"phaser": "^3.70.0",
"phaser3-rex-plugins": "^1.1.84"
},
@ -2723,6 +2724,11 @@
"node": ">= 0.6"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/cross-fetch": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
@ -4045,6 +4051,11 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -4072,6 +4083,11 @@
"node": ">=0.8.19"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ini": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
@ -4481,6 +4497,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
"dependencies": {
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"setimmediate": "^1.0.5"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@ -4648,6 +4675,14 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
@ -5237,6 +5272,11 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
},
"node_modules/papaparse": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
@ -5485,6 +5525,11 @@
"node": ">= 0.8.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@ -5551,6 +5596,25 @@
}
]
},
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/readable-stream/node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/rechoir": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
@ -5741,6 +5805,11 @@
"tslib": "^2.1.0"
}
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/safe-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz",
@ -5800,6 +5869,11 @@
"node": ">= 0.4"
}
},
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -5917,6 +5991,14 @@
"dev": true,
"license": "MIT"
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
@ -6473,6 +6555,11 @@
"requires-port": "^1.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/vite": {
"version": "5.4.8",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",

View File

@ -55,6 +55,7 @@
"i18next-http-backend": "^2.6.1",
"i18next-korean-postposition-processor": "^1.0.0",
"json-stable-stringify": "^1.1.0",
"jszip": "^3.10.1",
"phaser": "^3.70.0",
"phaser3-rex-plugins": "^1.1.84"
},

View File

@ -51,7 +51,7 @@ import { Biome } from "#enums/biome";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import { getPokemonNameWithAffix } from "#app/messages";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { FaintPhase } from "#app/phases/faint-phase";
import { LearnMovePhase } from "#app/phases/learn-move-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
@ -3005,7 +3005,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns integer of damage done
*/
damageAndUpdate(damage: integer, result?: DamageResult, critical: boolean = false, ignoreSegments: boolean = false, preventEndure: boolean = false, ignoreFaintPhase: boolean = false, source?: Pokemon): integer {
const damagePhase = new DamagePhase(this.scene, this.getBattlerIndex(), damage, result as DamageResult, critical);
const damagePhase = new DamageAnimPhase(this.scene, this.getBattlerIndex(), damage, result as DamageResult, critical);
this.scene.unshiftPhase(damagePhase);
damage = this.damage(damage, ignoreSegments, preventEndure, ignoreFaintPhase);
// Damage amount may have changed, but needed to be queued before calling damage function

View File

@ -1,11 +1,11 @@
import BattleScene from "#app/battle-scene";
import { BattlerIndex } from "#app/battle";
import { BattleSpec } from "#app/enums/battle-spec";
import { DamageResult, HitResult } from "#app/field/pokemon";
import * as Utils from "#app/utils";
import { PokemonPhase } from "./pokemon-phase";
import type BattleScene from "#app/battle-scene";
import { type BattlerIndex } from "#app/battle";
import { BattleSpec } from "#enums/battle-spec";
import { type DamageResult, HitResult } from "#app/field/pokemon";
import { fixedInt } from "#app/utils";
import { PokemonPhase } from "#app/phases/pokemon-phase";
export class DamagePhase extends PokemonPhase {
export class DamageAnimPhase extends PokemonPhase {
private amount: integer;
private damageResult: DamageResult;
private critical: boolean;
@ -25,7 +25,7 @@ export class DamagePhase extends PokemonPhase {
if (this.scene.moveAnimations) {
this.scene.toggleInvert(true);
}
this.scene.time.delayedCall(Utils.fixedInt(1000), () => {
this.scene.time.delayedCall(fixedInt(1000), () => {
this.scene.toggleInvert(false);
this.applyDamage();
});

View File

@ -12,7 +12,7 @@ import { getPokemonNameWithAffix } from "#app/messages";
import { PokemonInstantReviveModifier } from "#app/modifier/modifier";
import { SwitchType } from "#enums/switch-type";
import i18next from "i18next";
import { DamagePhase } from "./damage-phase";
import { DamageAnimPhase } from "./damage-anim-phase";
import { GameOverPhase } from "./game-over-phase";
import { PokemonPhase } from "./pokemon-phase";
import { SwitchPhase } from "./switch-phase";
@ -206,7 +206,7 @@ export class FaintPhase extends PokemonPhase {
} else {
// Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase
enemy.hp++;
this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER));
this.scene.unshiftPhase(new DamageAnimPhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER));
this.end();
}
return true;

View File

@ -2,7 +2,7 @@ import { BattlerIndex } from "#app/battle";
import { allAbilities } from "#app/data/ability";
import { Abilities } from "#app/enums/abilities";
import { WeatherType } from "#app/enums/weather-type";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { MovePhase } from "#app/phases/move-phase";
import { PostSummonPhase } from "#app/phases/post-summon-phase";
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
@ -273,7 +273,7 @@ describe("Abilities - Forecast", () => {
const castform = game.scene.getPlayerPokemon()!;
// Damage phase should come first
await game.phaseInterceptor.to(DamagePhase);
await game.phaseInterceptor.to(DamageAnimPhase);
expect(castform.hp).toBeLessThan(castform.getMaxHp());
// Then change form

View File

@ -42,7 +42,7 @@ describe("Abilities - Hustle", () => {
game.move.select(Moves.TACKLE);
await game.move.forceHit();
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(pikachu.getEffectiveStat).toHaveReturnedWith(Math.floor(atk * 1.5));
});
@ -68,7 +68,7 @@ describe("Abilities - Hustle", () => {
vi.spyOn(pikachu, "getAccuracyMultiplier");
game.move.select(Moves.GIGA_DRAIN);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(pikachu.getEffectiveStat).toHaveReturnedWith(spatk);
expect(pikachu.getAccuracyMultiplier).toHaveReturnedWith(1);
@ -86,7 +86,7 @@ describe("Abilities - Hustle", () => {
vi.spyOn(allMoves[Moves.FISSURE], "calculateBattleAccuracy");
game.move.select(Moves.FISSURE);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(enemyPokemon.turnData.damageTaken).toBe(enemyPokemon.getMaxHp());
expect(pikachu.getAccuracyMultiplier).toHaveReturnedWith(1);

View File

@ -51,7 +51,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
const firstStrikeDamage = enemyStartingHp - enemyPokemon.hp;
enemyStartingHp = enemyPokemon.hp;
@ -129,7 +129,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.SELF_DESTRUCT);
await game.phaseInterceptor.to("DamagePhase", false);
await game.phaseInterceptor.to("DamageAnimPhase", false);
expect(leadPokemon.turnData.hitCount).toBe(1);
}
@ -147,7 +147,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.ROLLOUT);
await game.move.forceHit();
await game.phaseInterceptor.to("DamagePhase", false);
await game.phaseInterceptor.to("DamageAnimPhase", false);
expect(leadPokemon.turnData.hitCount).toBe(1);
}
@ -181,7 +181,7 @@ describe("Abilities - Parental Bond", () => {
const enemyPokemon = game.scene.getEnemyPokemon()!;
game.move.select(Moves.COUNTER);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
const playerDamage = leadPokemon.getMaxHp() - leadPokemon.hp;
@ -221,7 +221,7 @@ describe("Abilities - Parental Bond", () => {
const leadPokemon = game.scene.getPlayerPokemon()!;
game.move.select(Moves.EARTHQUAKE);
await game.phaseInterceptor.to("DamagePhase", false);
await game.phaseInterceptor.to("DamageAnimPhase", false);
expect(leadPokemon.turnData.hitCount).toBe(2);
}
@ -238,7 +238,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.MIND_BLOWN);
await game.phaseInterceptor.to("DamagePhase", false);
await game.phaseInterceptor.to("DamageAnimPhase", false);
expect(leadPokemon.turnData.hitCount).toBe(2);
@ -285,7 +285,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(leadPokemon.turnData.hitCount).toBe(3);
}
@ -307,7 +307,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.SEISMIC_TOSS);
await game.move.forceHit();
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(leadPokemon.turnData.hitCount).toBe(3);
@ -329,7 +329,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.HYPER_BEAM);
await game.move.forceHit();
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(leadPokemon.turnData.hitCount).toBe(2);
expect(leadPokemon.getTag(BattlerTagType.RECHARGING)).toBeUndefined();
@ -353,7 +353,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.ANCHOR_SHOT);
await game.move.forceHit();
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(leadPokemon.turnData.hitCount).toBe(2);
expect(enemyPokemon.getTag(BattlerTagType.TRAPPED)).toBeUndefined();
@ -380,7 +380,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.SMACK_DOWN);
await game.move.forceHit();
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(leadPokemon.turnData.hitCount).toBe(2);
expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeUndefined();
@ -424,7 +424,7 @@ describe("Abilities - Parental Bond", () => {
game.move.select(Moves.WAKE_UP_SLAP);
await game.move.forceHit();
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(leadPokemon.turnData.hitCount).toBe(2);
expect(enemyPokemon.status?.effect).toBe(StatusEffect.SLEEP);

View File

@ -28,7 +28,9 @@ describe("Abilities - Speed Boost", () => {
game.override
.battleType("single")
.enemySpecies(Species.DRAGAPULT)
.enemySpecies(Species.SHUCKLE)
.enemyAbility(Abilities.BALL_FETCH)
.enemyLevel(100)
.ability(Abilities.SPEED_BOOST)
.enemyMoveset(Moves.SPLASH)
.moveset([ Moves.SPLASH, Moves.U_TURN ]);
@ -70,21 +72,23 @@ describe("Abilities - Speed Boost", () => {
Species.NINJASK
]);
game.move.select(Moves.U_TURN);
game.doSelectPartyPokemon(1);
await game.toNextTurn();
let playerPokemon = game.scene.getPlayerPokemon()!;
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(0);
const [ shuckle, ninjask ] = game.scene.getPlayerParty();
game.move.select(Moves.U_TURN);
game.doSelectPartyPokemon(1);
await game.toNextTurn();
playerPokemon = game.scene.getPlayerPokemon()!;
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(0);
expect(game.scene.getPlayerPokemon()!).toBe(ninjask);
expect(ninjask.getStatStage(Stat.SPD)).toBe(0);
game.move.select(Moves.U_TURN);
game.doSelectPartyPokemon(1);
await game.toNextTurn();
expect(game.scene.getPlayerPokemon()!).toBe(shuckle);
expect(shuckle.getStatStage(Stat.SPD)).toBe(0);
game.move.select(Moves.SPLASH);
await game.toNextTurn();
expect(playerPokemon.getStatStage(Stat.SPD)).toBe(1);
expect(shuckle.getStatStage(Stat.SPD)).toBe(1);
});
it("should not trigger this turn if pokemon was switched into combat via normal switch, but the turn after",

View File

@ -1,5 +1,5 @@
import { EnemyPokemon } from "#app/field/pokemon";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { MoveEndPhase } from "#app/phases/move-end-phase";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
@ -55,7 +55,7 @@ describe("Abilities - Sturdy", () => {
enemyPokemon.hp = enemyPokemon.getMaxHp() - 1;
game.move.select(Moves.CLOSE_COMBAT);
await game.phaseInterceptor.to(DamagePhase);
await game.phaseInterceptor.to(DamageAnimPhase);
expect(enemyPokemon.hp).toBe(0);
expect(enemyPokemon.isFainted()).toBe(true);
@ -81,7 +81,7 @@ describe("Abilities - Sturdy", () => {
await game.startBattle();
game.move.select(Moves.CLOSE_COMBAT);
await game.phaseInterceptor.to(DamagePhase);
await game.phaseInterceptor.to(DamageAnimPhase);
const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0];
expect(enemyPokemon.hp).toBe(0);

View File

@ -3,7 +3,7 @@ import { Stat } from "#enums/stat";
import { GameModes, getGameMode } from "#app/game-mode";
import { BattleEndPhase } from "#app/phases/battle-end-phase";
import { CommandPhase } from "#app/phases/command-phase";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { EncounterPhase } from "#app/phases/encounter-phase";
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
import { LoginPhase } from "#app/phases/login-phase";
@ -267,7 +267,7 @@ describe("Test Battle Phase", () => {
]);
game.move.select(moveToUse);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
await game.killPokemon(game.scene.currentBattle.enemyParty[0]);
expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true);
await game.phaseInterceptor.to(VictoryPhase, false);

View File

@ -102,7 +102,7 @@ describe("Battle Mechanics - Damage Calculation", () => {
game.move.select(Moves.JUMP_KICK);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(shedinja.hp).toBe(shedinja.getMaxHp() - 1);
});

View File

@ -1,4 +1,4 @@
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { TurnEndPhase } from "#app/phases/turn-end-phase";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
@ -48,7 +48,7 @@ describe("Items - Leftovers", () => {
game.move.select(Moves.SPLASH);
// We should have less hp after the attack
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp());
const leadHpAfterDamage = leadPokemon.hp;

View File

@ -1,6 +1,6 @@
import { BattlerIndex } from "#app/battle";
import { allMoves } from "#app/data/move";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
@ -51,7 +51,7 @@ describe("Moves - Dynamax Cannon", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(dynamaxCannon.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(100);
}, 20000);
@ -65,7 +65,7 @@ describe("Moves - Dynamax Cannon", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(dynamaxCannon.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(100);
}, 20000);
@ -82,7 +82,7 @@ describe("Moves - Dynamax Cannon", () => {
expect(phase.move.moveId).toBe(dynamaxCannon.id);
// Force level cap to be 100
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(120);
}, 20000);
@ -99,7 +99,7 @@ describe("Moves - Dynamax Cannon", () => {
expect(phase.move.moveId).toBe(dynamaxCannon.id);
// Force level cap to be 100
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(140);
}, 20000);
@ -116,7 +116,7 @@ describe("Moves - Dynamax Cannon", () => {
expect(phase.move.moveId).toBe(dynamaxCannon.id);
// Force level cap to be 100
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(160);
}, 20000);
@ -133,7 +133,7 @@ describe("Moves - Dynamax Cannon", () => {
expect(phase.move.moveId).toBe(dynamaxCannon.id);
// Force level cap to be 100
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(180);
}, 20000);
@ -150,7 +150,7 @@ describe("Moves - Dynamax Cannon", () => {
expect(phase.move.moveId).toBe(dynamaxCannon.id);
// Force level cap to be 100
vi.spyOn(phase.getFirstTarget()!.scene, "getMaxExpLevel").mockReturnValue(100);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
@ -165,7 +165,7 @@ describe("Moves - Dynamax Cannon", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(dynamaxCannon.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(dynamaxCannon.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
});

View File

@ -1,7 +1,7 @@
import { Stat } from "#enums/stat";
import { Species } from "#app/enums/species";
import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { TurnEndPhase } from "#app/phases/turn-end-phase";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
@ -56,7 +56,7 @@ describe("Moves - Fissure", () => {
game.override.enemyAbility(Abilities.FUR_COAT);
game.move.select(Moves.FISSURE);
await game.phaseInterceptor.to(DamagePhase, true);
await game.phaseInterceptor.to(DamageAnimPhase, true);
expect(enemyPokemon.isFainted()).toBe(true);
});

View File

@ -1,7 +1,7 @@
import { Stat } from "#enums/stat";
import { BattlerIndex } from "#app/battle";
import { allMoves } from "#app/data/move";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { MoveEndPhase } from "#app/phases/move-end-phase";
import { MovePhase } from "#app/phases/move-phase";
@ -58,12 +58,12 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(100);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
@ -81,12 +81,12 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
@ -104,7 +104,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(100);
await game.phaseInterceptor.to(MoveEndPhase);
@ -114,7 +114,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
@ -133,7 +133,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(100);
await game.phaseInterceptor.to(MoveEndPhase);
@ -142,7 +142,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100);
}, 20000);
@ -160,12 +160,12 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
@ -209,22 +209,22 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
@ -268,22 +268,22 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => {
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200);
await game.phaseInterceptor.to(MoveEffectPhase, false);
expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id);
await game.phaseInterceptor.to(DamagePhase, false);
await game.phaseInterceptor.to(DamageAnimPhase, false);
expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200);
}, 20000);
});

View File

@ -41,11 +41,11 @@ describe("Moves - Glaive Rush", () => {
enemy.hp = 1000;
game.move.select(Moves.SHADOW_SNEAK);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
const damageDealt = 1000 - enemy.hp;
await game.phaseInterceptor.to("TurnEndPhase");
game.move.select(Moves.SHADOW_SNEAK);
await game.phaseInterceptor.to("DamagePhase");
await game.phaseInterceptor.to("DamageAnimPhase");
expect(enemy.hp).toBeLessThanOrEqual(1001 - (damageDealt * 3));
});

View File

@ -1,6 +1,6 @@
import { BattlerIndex } from "#app/battle";
import { allMoves } from "#app/data/move";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { MoveEndPhase } from "#app/phases/move-end-phase";
import { TurnEndPhase } from "#app/phases/turn-end-phase";
@ -48,7 +48,7 @@ describe("Moves - Scale Shot", () => {
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
await game.phaseInterceptor.to(MoveEffectPhase);
await game.phaseInterceptor.to(DamagePhase);
await game.phaseInterceptor.to(DamageAnimPhase);
//check that stats haven't changed after one or two hits have occurred
await game.phaseInterceptor.to(MoveEffectPhase);

View File

@ -33,7 +33,7 @@ export async function runMysteryEncounterToEnd(game: GameManager, optionNo: numb
}, () => game.isCurrentPhase(MysteryEncounterBattlePhase) || game.isCurrentPhase(MysteryEncounterRewardsPhase));
if (isBattle) {
game.onNextPrompt("DamagePhase", Mode.MESSAGE, () => {
game.onNextPrompt("DamageAnimPhase", Mode.MESSAGE, () => {
game.setMode(Mode.MESSAGE);
game.endPhase();
}, () => game.isCurrentPhase(CommandPhase));

View File

@ -5,7 +5,7 @@ import { BattleEndPhase } from "#app/phases/battle-end-phase";
import { BerryPhase } from "#app/phases/berry-phase";
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
import { CommandPhase } from "#app/phases/command-phase";
import { DamagePhase } from "#app/phases/damage-phase";
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
import { EncounterPhase } from "#app/phases/encounter-phase";
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
@ -87,7 +87,7 @@ type PhaseClass =
| typeof TurnStartPhase
| typeof MovePhase
| typeof MoveEffectPhase
| typeof DamagePhase
| typeof DamageAnimPhase
| typeof FaintPhase
| typeof BerryPhase
| typeof TurnEndPhase
@ -146,7 +146,7 @@ type PhaseString =
| "TurnStartPhase"
| "MovePhase"
| "MoveEffectPhase"
| "DamagePhase"
| "DamageAnimPhase"
| "FaintPhase"
| "BerryPhase"
| "TurnEndPhase"
@ -229,7 +229,7 @@ export default class PhaseInterceptor {
[ TurnStartPhase, this.startPhase ],
[ MovePhase, this.startPhase ],
[ MoveEffectPhase, this.startPhase ],
[ DamagePhase, this.startPhase ],
[ DamageAnimPhase, this.startPhase ],
[ FaintPhase, this.startPhase ],
[ BerryPhase, this.startPhase ],
[ TurnEndPhase, this.startPhase ],

View File

@ -8,6 +8,7 @@ import { addTextObject, TextStyle } from "./text";
import { addWindow } from "./ui-theme";
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
import JSZip from "jszip";
interface BuildInteractableImageOpts {
scale?: number;
@ -27,6 +28,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
private googleImage: Phaser.GameObjects.Image;
private discordImage: Phaser.GameObjects.Image;
private usernameInfoImage: Phaser.GameObjects.Image;
private saveDownloadImage: Phaser.GameObjects.Image;
private externalPartyContainer: Phaser.GameObjects.Container;
private infoContainer: Phaser.GameObjects.Container;
private externalPartyBg: Phaser.GameObjects.NineSlice;
@ -46,7 +48,13 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
scale: 0.5
});
this.saveDownloadImage = this.buildInteractableImage("saving_icon", "save-download-icon", {
x: 0,
scale: 0.75
});
this.infoContainer.add(this.usernameInfoImage);
this.infoContainer.add(this.saveDownloadImage);
this.getUi().add(this.infoContainer);
this.infoContainer.setVisible(false);
this.infoContainer.disableInteractive();
@ -160,7 +168,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
this.infoContainer.setVisible(false);
this.setMouseCursorStyle("default"); //reset cursor
[ this.discordImage, this.googleImage, this.usernameInfoImage ].forEach((img) => img.off("pointerdown"));
[ this.discordImage, this.googleImage, this.usernameInfoImage, this.saveDownloadImage ].forEach((img) => img.off("pointerdown"));
}
private processExternalProvider(config: ModalConfig): void {
@ -178,6 +186,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
this.infoContainer.setVisible(true);
this.getUi().moveTo(this.infoContainer, this.getUi().length - 1);
this.usernameInfoImage.setPositionRelative(this.infoContainer, 0, 0);
this.saveDownloadImage.setPositionRelative(this.infoContainer, 20, 0);
this.discordImage.on("pointerdown", () => {
const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`);
@ -229,6 +238,34 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
}
});
this.saveDownloadImage.on("pointerdown", () => {
// find all data_ and sessionData keys, put them in a .txt file and download everything in a single zip
const localStorageKeys = Object.keys(localStorage); // this gets the keys for localStorage
const keyToFind = "data_";
const sessionKeyToFind = "sessionData";
const dataKeys = localStorageKeys.filter(ls => ls.indexOf(keyToFind) >= 0);
const sessionKeys = localStorageKeys.filter(ls => ls.indexOf(sessionKeyToFind) >= 0);
if (dataKeys.length > 0 || sessionKeys.length > 0) {
const zip = new JSZip();
for (let i = 0; i < dataKeys.length; i++) {
zip.file(dataKeys[i] + ".prsv", localStorage.getItem(dataKeys[i])!);
}
for (let i = 0; i < sessionKeys.length; i++) {
zip.file(sessionKeys[i] + ".prsv", localStorage.getItem(sessionKeys[i])!);
}
zip.generateAsync({ type: "blob" }).then(content => {
const url = URL.createObjectURL(content);
const a = document.createElement("a");
a.href = url;
a.download = "pokerogue_saves.zip";
a.click();
URL.revokeObjectURL(url);
});
} else {
return onFail(this.ERR_NO_SAVES);
}
});
this.externalPartyContainer.setAlpha(0);
this.scene.tweens.add({
targets: this.externalPartyContainer,