[Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067)
* fix scrappy + etc. update inverse battle test code * update test code following request from swain
This commit is contained in:
parent
675e6a0635
commit
45af0dd170
|
@ -1427,22 +1427,26 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
let multiplier = types.map(defType => {
|
||||
const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType));
|
||||
applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier);
|
||||
if (source) {
|
||||
const ignoreImmunity = new Utils.BooleanHolder(false);
|
||||
if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) {
|
||||
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType);
|
||||
}
|
||||
if (ignoreImmunity.value) {
|
||||
return 1;
|
||||
if (multiplier.value === 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const exposedTags = this.findTags(tag => tag instanceof ExposedTag) as ExposedTag[];
|
||||
if (exposedTags.some(t => t.ignoreImmunity(defType, moveType))) {
|
||||
return 1;
|
||||
if (multiplier.value === 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType));
|
||||
applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier);
|
||||
return multiplier.value;
|
||||
}).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier;
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
import { BattlerIndex } from "#app/battle";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { Type } from "#app/data/type";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
import { TurnEndPhase } from "#app/phases/turn-end-phase";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
|
@ -11,7 +8,8 @@ import { Species } from "#enums/species";
|
|||
import { StatusEffect } from "#enums/status-effect";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import { SPLASH_ONLY } from "#test/utils/testUtils";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
|
@ -39,43 +37,63 @@ describe("Inverse Battle", () => {
|
|||
.starterSpecies(Species.FEEBAS)
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyAbility(Abilities.BALL_FETCH);
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(SPLASH_ONLY);
|
||||
});
|
||||
|
||||
it("1. immune types are 2x effective - Thunderbolt against Ground Type", async () => {
|
||||
game.override.enemySpecies(Species.SANDSHREW);
|
||||
it("Immune types are 2x effective - Thunderbolt against Ground Type", async () => {
|
||||
game.override
|
||||
.moveset([Moves.THUNDERBOLT])
|
||||
.enemySpecies(Species.SANDSHREW);
|
||||
|
||||
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
expect(enemy.getMoveEffectiveness(player, allMoves[Moves.THUNDERBOLT])).toBe(2);
|
||||
game.move.select(Moves.THUNDERBOLT);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
||||
expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("2. 2x effective types are 0.5x effective - Thunderbolt against Flying Type", async () => {
|
||||
game.override.enemySpecies(Species.PIDGEY);
|
||||
it("2x effective types are 0.5x effective - Thunderbolt against Flying Type", async () => {
|
||||
game.override
|
||||
.moveset([Moves.THUNDERBOLT])
|
||||
.enemySpecies(Species.PIDGEY);
|
||||
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
expect(enemy.getMoveEffectiveness(player, allMoves[Moves.THUNDERBOLT])).toBe(0.5);
|
||||
game.move.select(Moves.THUNDERBOLT);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
||||
expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.5);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("3. 0.5x effective types are 2x effective - Thunderbolt against Electric Type", async () => {
|
||||
game.override.enemySpecies(Species.CHIKORITA);
|
||||
it("0.5x effective types are 2x effective - Thunderbolt against Electric Type", async () => {
|
||||
game.override
|
||||
.moveset([Moves.THUNDERBOLT])
|
||||
.enemySpecies(Species.CHIKORITA);
|
||||
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
expect(enemy.getMoveEffectiveness(player, allMoves[Moves.THUNDERBOLT])).toBe(2);
|
||||
game.move.select(Moves.THUNDERBOLT);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
||||
expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("4. Stealth Rock follows the inverse matchups - Stealth Rock against Charizard deals 1/32 of max HP", async () => {
|
||||
it("Stealth Rock follows the inverse matchups - Stealth Rock against Charizard deals 1/32 of max HP", async () => {
|
||||
game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 1, Moves.STEALTH_ROCK, 0);
|
||||
game.override
|
||||
.enemySpecies(Species.CHARIZARD)
|
||||
|
@ -95,18 +113,24 @@ describe("Inverse Battle", () => {
|
|||
expect(currentHp).toBeGreaterThan(maxHp * 31 / 32 - 1);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("5. Freeze Dry is 2x effective against Water Type like other Ice type Move - Freeze Dry against Squirtle", async () => {
|
||||
game.override.enemySpecies(Species.SQUIRTLE);
|
||||
it("Freeze Dry is 2x effective against Water Type like other Ice type Move - Freeze Dry against Squirtle", async () => {
|
||||
game.override
|
||||
.moveset([Moves.FREEZE_DRY])
|
||||
.enemySpecies(Species.SQUIRTLE);
|
||||
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
expect(enemy.getMoveEffectiveness(player, allMoves[Moves.FREEZE_DRY])).toBe(2);
|
||||
game.move.select(Moves.FREEZE_DRY);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
||||
expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("6. Water Absorb should heal against water moves - Water Absorb against Water gun", async () => {
|
||||
it("Water Absorb should heal against water moves - Water Absorb against Water gun", async () => {
|
||||
game.override
|
||||
.moveset([Moves.WATER_GUN])
|
||||
.enemyAbility(Abilities.WATER_ABSORB);
|
||||
|
@ -117,13 +141,12 @@ describe("Inverse Battle", () => {
|
|||
enemy.hp = enemy.getMaxHp() - 1;
|
||||
game.move.select(Moves.WATER_GUN);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
|
||||
expect(enemy.hp).toBe(enemy.getMaxHp());
|
||||
}, TIMEOUT);
|
||||
|
||||
it("7. Fire type does not get burned - Will-O-Wisp against Charmander", async () => {
|
||||
it("Fire type does not get burned - Will-O-Wisp against Charmander", async () => {
|
||||
game.override
|
||||
.moveset([Moves.WILL_O_WISP])
|
||||
.enemySpecies(Species.CHARMANDER);
|
||||
|
@ -135,13 +158,12 @@ describe("Inverse Battle", () => {
|
|||
game.move.select(Moves.WILL_O_WISP);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.move.forceHit();
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
|
||||
expect(enemy.status?.effect).not.toBe(StatusEffect.BURN);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("8. Electric type does not get paralyzed - Nuzzle against Pikachu", async () => {
|
||||
it("Electric type does not get paralyzed - Nuzzle against Pikachu", async () => {
|
||||
game.override
|
||||
.moveset([Moves.NUZZLE])
|
||||
.enemySpecies(Species.PIKACHU)
|
||||
|
@ -153,14 +175,30 @@ describe("Inverse Battle", () => {
|
|||
|
||||
game.move.select(Moves.NUZZLE);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
|
||||
expect(enemy.status?.effect).not.toBe(StatusEffect.PARALYSIS);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("Ground type is not immune to Thunder Wave - Thunder Wave against Sandshrew", async () => {
|
||||
game.override
|
||||
.moveset([Moves.THUNDER_WAVE])
|
||||
.enemySpecies(Species.SANDSHREW);
|
||||
|
||||
it("10. Anticipation should trigger on 2x effective moves - Anticipation against Thunderbolt", async () => {
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
|
||||
game.move.select(Moves.THUNDER_WAVE);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.move.forceHit();
|
||||
await game.phaseInterceptor.to("MoveEndPhase");
|
||||
|
||||
expect(enemy.status?.effect).toBe(StatusEffect.PARALYSIS);
|
||||
}, TIMEOUT);
|
||||
|
||||
|
||||
it("Anticipation should trigger on 2x effective moves - Anticipation against Thunderbolt", async () => {
|
||||
game.override
|
||||
.moveset([Moves.THUNDERBOLT])
|
||||
.enemySpecies(Species.SANDSHREW)
|
||||
|
@ -171,7 +209,7 @@ describe("Inverse Battle", () => {
|
|||
expect(game.scene.getEnemyPokemon()?.summonData.abilitiesApplied[0]).toBe(Abilities.ANTICIPATION);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("11. Conversion 2 should change the type to the resistive type - Conversion 2 against Dragonite", async () => {
|
||||
it("Conversion 2 should change the type to the resistive type - Conversion 2 against Dragonite", async () => {
|
||||
game.override
|
||||
.moveset([Moves.CONVERSION_2])
|
||||
.enemyMoveset([Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW]);
|
||||
|
@ -183,21 +221,64 @@ describe("Inverse Battle", () => {
|
|||
game.move.select(Moves.CONVERSION_2);
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(player.getTypes()[0]).toBe(Type.DRAGON);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("12. Flying Press should be 0.25x effective against Grass + Dark Type - Flying Press against Meowscarada", async () => {
|
||||
it("Flying Press should be 0.25x effective against Grass + Dark Type - Flying Press against Meowscarada", async () => {
|
||||
game.override
|
||||
.moveset([Moves.FLYING_PRESS])
|
||||
.enemySpecies(Species.MEOWSCARADA);
|
||||
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const player = game.scene.getPlayerPokemon()!;
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
expect(enemy.getMoveEffectiveness(player, allMoves[Moves.FLYING_PRESS])).toBe(0.25);
|
||||
game.move.select(Moves.FLYING_PRESS);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
||||
expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.25);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("Scrappy ability has no effect - Tackle against Ghost Type still 2x effective with Scrappy", async () => {
|
||||
game.override
|
||||
.moveset([Moves.TACKLE])
|
||||
.ability(Abilities.SCRAPPY)
|
||||
.enemySpecies(Species.GASTLY);
|
||||
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(Moves.TACKLE);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
||||
expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("FORESIGHT has no effect - Tackle against Ghost Type still 2x effective with Foresight", async () => {
|
||||
game.override
|
||||
.moveset([Moves.FORESIGHT, Moves.TACKLE])
|
||||
.enemySpecies(Species.GASTLY);
|
||||
|
||||
await game.challengeMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(Moves.FORESIGHT);
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
game.move.select(Moves.TACKLE);
|
||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
|
||||
expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue