[Bug] Fix for Roost Grounds the User Rather than Removing Flying Typing#3984 (#4164)
* double checking tests on a new made branch for bug 3984 * roost test update * added roost test file * Roost test update * removed random stackdump * cleaned up message for roost * fixed test file for linter * cleaning up code and fixing some desync test issues * Cleaned up more code and added case for double shock * fixing some messages and putting burn up and double shock in same class --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
parent
ef4d2ec91e
commit
f80c073def
|
@ -1885,11 +1885,18 @@ export class CursedTag extends BattlerTag {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Battler tag for attacks that remove a type post use.
|
||||||
|
*/
|
||||||
|
export class RemovedTypeTag extends BattlerTag {
|
||||||
|
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, sourceMove: Moves) {
|
||||||
|
super(tagType, lapseType, 1, sourceMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Battler tag for effects that ground the source, allowing Ground-type moves to hit them. Encompasses two tag types:
|
* Battler tag for effects that ground the source, allowing Ground-type moves to hit them.
|
||||||
* @item `IGNORE_FLYING`: Persistent grounding effects (i.e. from Smack Down and Thousand Waves)
|
* @description `IGNORE_FLYING`: Persistent grounding effects (i.e. from Smack Down and Thousand Waves)
|
||||||
* @item `ROOSTED`: One-turn grounding effects (i.e. from Roost)
|
|
||||||
*/
|
*/
|
||||||
export class GroundedTag extends BattlerTag {
|
export class GroundedTag extends BattlerTag {
|
||||||
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, sourceMove: Moves) {
|
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, sourceMove: Moves) {
|
||||||
|
@ -1897,6 +1904,70 @@ export class GroundedTag extends BattlerTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description `ROOSTED`: Tag for temporary grounding if only source of ungrounding is flying and pokemon uses Roost.
|
||||||
|
* Roost removes flying type from a pokemon for a single turn.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class RoostedTag extends BattlerTag {
|
||||||
|
private isBaseFlying : boolean;
|
||||||
|
private isBasePureFlying : boolean;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(BattlerTagType.ROOSTED, BattlerTagLapseType.TURN_END, 1, Moves.ROOST);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemove(pokemon: Pokemon): void {
|
||||||
|
const currentTypes = pokemon.getTypes();
|
||||||
|
const baseTypes = pokemon.getTypes(false, false, true);
|
||||||
|
|
||||||
|
const forestsCurseApplied: boolean = currentTypes.includes(Type.GRASS) && !baseTypes.includes(Type.GRASS);
|
||||||
|
const trickOrTreatApplied: boolean = currentTypes.includes(Type.GHOST) && !baseTypes.includes(Type.GHOST);
|
||||||
|
|
||||||
|
if (this.isBaseFlying) {
|
||||||
|
let modifiedTypes: Type[] = [];
|
||||||
|
if (this.isBasePureFlying) {
|
||||||
|
if (forestsCurseApplied || trickOrTreatApplied) {
|
||||||
|
modifiedTypes = currentTypes.filter(type => type !== Type.NORMAL);
|
||||||
|
modifiedTypes.push(Type.FLYING);
|
||||||
|
} else {
|
||||||
|
modifiedTypes = [Type.FLYING];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
modifiedTypes = [...currentTypes];
|
||||||
|
modifiedTypes.push(Type.FLYING);
|
||||||
|
}
|
||||||
|
pokemon.summonData.types = modifiedTypes;
|
||||||
|
pokemon.updateInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd(pokemon: Pokemon): void {
|
||||||
|
const currentTypes = pokemon.getTypes();
|
||||||
|
const baseTypes = pokemon.getTypes(false, false, true);
|
||||||
|
|
||||||
|
const isOriginallyDualType = baseTypes.length === 2;
|
||||||
|
const isCurrentlyDualType = currentTypes.length === 2;
|
||||||
|
this.isBaseFlying = baseTypes.includes(Type.FLYING);
|
||||||
|
this.isBasePureFlying = baseTypes[0] === Type.FLYING && baseTypes.length === 1;
|
||||||
|
|
||||||
|
if (this.isBaseFlying) {
|
||||||
|
let modifiedTypes: Type[];
|
||||||
|
if (this.isBasePureFlying && !isCurrentlyDualType) {
|
||||||
|
modifiedTypes = [Type.NORMAL];
|
||||||
|
} else {
|
||||||
|
if (!!pokemon.getTag(RemovedTypeTag) && isOriginallyDualType && !isCurrentlyDualType) {
|
||||||
|
modifiedTypes = [Type.UNKNOWN];
|
||||||
|
} else {
|
||||||
|
modifiedTypes = currentTypes.filter(type => type !== Type.FLYING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pokemon.summonData.types = modifiedTypes;
|
||||||
|
pokemon.updateInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Common attributes of form change abilities that block damage */
|
/** Common attributes of form change abilities that block damage */
|
||||||
export class FormBlockDamageTag extends BattlerTag {
|
export class FormBlockDamageTag extends BattlerTag {
|
||||||
constructor(tagType: BattlerTagType) {
|
constructor(tagType: BattlerTagType) {
|
||||||
|
@ -2259,7 +2330,11 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
||||||
case BattlerTagType.IGNORE_FLYING:
|
case BattlerTagType.IGNORE_FLYING:
|
||||||
return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||||
case BattlerTagType.ROOSTED:
|
case BattlerTagType.ROOSTED:
|
||||||
return new GroundedTag(tagType, BattlerTagLapseType.TURN_END, sourceMove);
|
return new RoostedTag();
|
||||||
|
case BattlerTagType.BURNED_UP:
|
||||||
|
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||||
|
case BattlerTagType.DOUBLE_SHOCKED:
|
||||||
|
return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove);
|
||||||
case BattlerTagType.SALT_CURED:
|
case BattlerTagType.SALT_CURED:
|
||||||
return new SaltCuredTag(sourceId);
|
return new SaltCuredTag(sourceId);
|
||||||
case BattlerTagType.CURSED:
|
case BattlerTagType.CURSED:
|
||||||
|
|
|
@ -8532,6 +8532,7 @@ export function initMoves() {
|
||||||
return userTypes.includes(Type.FIRE);
|
return userTypes.includes(Type.FIRE);
|
||||||
})
|
})
|
||||||
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
.attr(HealStatusEffectAttr, true, StatusEffect.FREEZE)
|
||||||
|
.attr(AddBattlerTagAttr, BattlerTagType.BURNED_UP, true, false)
|
||||||
.attr(RemoveTypeAttr, Type.FIRE, (user) => {
|
.attr(RemoveTypeAttr, Type.FIRE, (user) => {
|
||||||
user.scene.queueMessage(i18next.t("moveTriggers:burnedItselfOut", {pokemonName: getPokemonNameWithAffix(user)}));
|
user.scene.queueMessage(i18next.t("moveTriggers:burnedItselfOut", {pokemonName: getPokemonNameWithAffix(user)}));
|
||||||
}),
|
}),
|
||||||
|
@ -9315,6 +9316,7 @@ export function initMoves() {
|
||||||
const userTypes = user.getTypes(true);
|
const userTypes = user.getTypes(true);
|
||||||
return userTypes.includes(Type.ELECTRIC);
|
return userTypes.includes(Type.ELECTRIC);
|
||||||
})
|
})
|
||||||
|
.attr(AddBattlerTagAttr, BattlerTagType.DOUBLE_SHOCKED, true, false)
|
||||||
.attr(RemoveTypeAttr, Type.ELECTRIC, (user) => {
|
.attr(RemoveTypeAttr, Type.ELECTRIC, (user) => {
|
||||||
user.scene.queueMessage(i18next.t("moveTriggers:usedUpAllElectricity", {pokemonName: getPokemonNameWithAffix(user)}));
|
user.scene.queueMessage(i18next.t("moveTriggers:usedUpAllElectricity", {pokemonName: getPokemonNameWithAffix(user)}));
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -76,4 +76,6 @@ export enum BattlerTagType {
|
||||||
GORILLA_TACTICS = "GORILLA_TACTICS",
|
GORILLA_TACTICS = "GORILLA_TACTICS",
|
||||||
THROAT_CHOPPED = "THROAT_CHOPPED",
|
THROAT_CHOPPED = "THROAT_CHOPPED",
|
||||||
TAR_SHOT = "TAR_SHOT",
|
TAR_SHOT = "TAR_SHOT",
|
||||||
|
BURNED_UP = "BURNED_UP",
|
||||||
|
DOUBLE_SHOCKED = "DOUBLE_SHOCKED",
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Abilities } from "#app/enums/abilities";
|
import { Type } from "#app/data/type";
|
||||||
import { BattlerTagType } from "#app/enums/battler-tag-type";
|
import { BattlerTagType } from "#app/enums/battler-tag-type";
|
||||||
import { Moves } from "#app/enums/moves";
|
import { Moves } from "#app/enums/moves";
|
||||||
import { Species } from "#app/enums/species";
|
import { Species } from "#app/enums/species";
|
||||||
|
@ -27,33 +27,234 @@ describe("Moves - Roost", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleType("single");
|
game.override.battleType("single");
|
||||||
game.override.enemySpecies(Species.STARAPTOR);
|
game.override.enemySpecies(Species.RELICANTH);
|
||||||
game.override.enemyAbility(Abilities.INSOMNIA);
|
|
||||||
game.override.startingLevel(100);
|
game.override.startingLevel(100);
|
||||||
game.override.enemyLevel(100);
|
game.override.enemyLevel(60);
|
||||||
game.override.moveset([Moves.STOMPING_TANTRUM]);
|
game.override.enemyMoveset(Moves.EARTHQUAKE);
|
||||||
game.override.enemyMoveset([Moves.ROOST, Moves.ROOST, Moves.ROOST, Moves.ROOST]);
|
game.override.moveset([Moves.ROOST, Moves.BURN_UP, Moves.DOUBLE_SHOCK]);
|
||||||
|
game.override.starterForms({ [Species.ROTOM]: 4 });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Roost's behavior should be defined as:
|
||||||
|
* The pokemon loses its flying type for a turn. If the pokemon was ungroundd solely due to being a flying type, it will be grounded until end of turn.
|
||||||
|
* 1. Pure Flying type pokemon -> become normal type until end of turn
|
||||||
|
* 2. Dual Flying/X type pokemon -> become type X until end of turn
|
||||||
|
* 3. Pokemon that use burn up into roost (ex. Moltres) -> become flying due to burn up, then typeless until end of turn after using roost
|
||||||
|
* 4. If a pokemon is afflicted with Forest's Curse or Trick or treat, dual type pokemon will become 3 type pokemon after the flying type is regained
|
||||||
|
* Pure flying types become (Grass or Ghost) and then back to flying/ (Grass or Ghost),
|
||||||
|
* and pokemon post Burn up become ()
|
||||||
|
* 5. If a pokemon is also ungrounded due to other reasons (such as levitate), it will stay ungrounded post roost, despite not being flying type.
|
||||||
|
* 6. Non flying types using roost (such as dunsparce) are already grounded, so this move will only heal and have no other effects.
|
||||||
|
*/
|
||||||
|
|
||||||
test(
|
test(
|
||||||
"move should ground the user until the end of turn",
|
"Non flying type uses roost -> no type change, took damage",
|
||||||
async () => {
|
async () => {
|
||||||
await game.startBattle([Species.MAGIKARP]);
|
await game.classicMode.startBattle([Species.DUNSPARCE]);
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const playerPokemonStartingHP = playerPokemon.hp;
|
||||||
|
game.move.select(Moves.ROOST);
|
||||||
const enemyStartingHp = enemyPokemon.hp;
|
|
||||||
|
|
||||||
game.move.select(Moves.STOMPING_TANTRUM);
|
|
||||||
|
|
||||||
await game.phaseInterceptor.to(MoveEffectPhase);
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
expect(enemyPokemon.getTag(BattlerTagType.ROOSTED)).toBeDefined();
|
// Should only be normal type, and NOT flying type
|
||||||
|
let playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes[0] === Type.NORMAL).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeTruthy();
|
||||||
|
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp);
|
// Lose HP, still normal type
|
||||||
expect(enemyPokemon.getTag(BattlerTagType.ROOSTED)).toBeUndefined();
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.hp).toBeLessThan(playerPokemonStartingHP);
|
||||||
|
expect(playerPokemonTypes[0] === Type.NORMAL).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeTruthy();
|
||||||
}, TIMEOUT
|
}, TIMEOUT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
"Pure flying type -> becomes normal after roost and takes damage from ground moves -> regains flying",
|
||||||
|
async () => {
|
||||||
|
await game.classicMode.startBattle([Species.TORNADUS]);
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const playerPokemonStartingHP = playerPokemon.hp;
|
||||||
|
game.move.select(Moves.ROOST);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
// Should only be normal type, and NOT flying type
|
||||||
|
let playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes[0] === Type.NORMAL).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes[0] === Type.FLYING).toBeFalsy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeTruthy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
// Should have lost HP and is now back to being pure flying
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.hp).toBeLessThan(playerPokemonStartingHP);
|
||||||
|
expect(playerPokemonTypes[0] === Type.NORMAL).toBeFalsy();
|
||||||
|
expect(playerPokemonTypes[0] === Type.FLYING).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeFalsy();
|
||||||
|
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
"Dual X/flying type -> becomes type X after roost and takes damage from ground moves -> regains flying",
|
||||||
|
async () => {
|
||||||
|
await game.classicMode.startBattle([Species.HAWLUCHA]);
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const playerPokemonStartingHP = playerPokemon.hp;
|
||||||
|
game.move.select(Moves.ROOST);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
// Should only be pure fighting type and grounded
|
||||||
|
let playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes[0] === Type.FIGHTING).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeTruthy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
// Should have lost HP and is now back to being fighting/flying
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.hp).toBeLessThan(playerPokemonStartingHP);
|
||||||
|
expect(playerPokemonTypes[0] === Type.FIGHTING).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes[1] === Type.FLYING).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeFalsy();
|
||||||
|
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
"Pokemon with levitate after using roost should lose flying type but still be unaffected by ground moves",
|
||||||
|
async () => {
|
||||||
|
await game.classicMode.startBattle([Species.ROTOM]);
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const playerPokemonStartingHP = playerPokemon.hp;
|
||||||
|
game.move.select(Moves.ROOST);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
// Should only be pure fighting type and grounded
|
||||||
|
let playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes[0] === Type.ELECTRIC).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeFalsy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
// Should have lost HP and is now back to being fighting/flying
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.hp).toBe(playerPokemonStartingHP);
|
||||||
|
expect(playerPokemonTypes[0] === Type.ELECTRIC).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes[1] === Type.FLYING).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeFalsy();
|
||||||
|
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
"A fire/flying type that uses burn up, then roost should be typeless until end of turn",
|
||||||
|
async () => {
|
||||||
|
await game.classicMode.startBattle([Species.MOLTRES]);
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const playerPokemonStartingHP = playerPokemon.hp;
|
||||||
|
game.move.select(Moves.BURN_UP);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
// Should only be pure flying type after burn up
|
||||||
|
let playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes[0] === Type.FLYING).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
game.move.select(Moves.ROOST);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
// Should only be typeless type after roost and is grounded
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.getTag(BattlerTagType.ROOSTED)).toBeDefined();
|
||||||
|
expect(playerPokemonTypes[0] === Type.UNKNOWN).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeTruthy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
// Should go back to being pure flying and have taken damage from earthquake, and is ungrounded again
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.hp).toBeLessThan(playerPokemonStartingHP);
|
||||||
|
expect(playerPokemonTypes[0] === Type.FLYING).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeFalsy();
|
||||||
|
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
"An electric/flying type that uses double shock, then roost should be typeless until end of turn",
|
||||||
|
async () => {
|
||||||
|
game.override.enemySpecies(Species.ZEKROM);
|
||||||
|
await game.classicMode.startBattle([Species.ZAPDOS]);
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const playerPokemonStartingHP = playerPokemon.hp;
|
||||||
|
game.move.select(Moves.DOUBLE_SHOCK);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
// Should only be pure flying type after burn up
|
||||||
|
let playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes[0] === Type.FLYING).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
game.move.select(Moves.ROOST);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
// Should only be typeless type after roost and is grounded
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.getTag(BattlerTagType.ROOSTED)).toBeDefined();
|
||||||
|
expect(playerPokemonTypes[0] === Type.UNKNOWN).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeTruthy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
// Should go back to being pure flying and have taken damage from earthquake, and is ungrounded again
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemon.hp).toBeLessThan(playerPokemonStartingHP);
|
||||||
|
expect(playerPokemonTypes[0] === Type.FLYING).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeFalsy();
|
||||||
|
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
"Dual Type Pokemon afflicted with Forests Curse/Trick or Treat and post roost will become dual type and then become 3 type at end of turn",
|
||||||
|
async () => {
|
||||||
|
game.override.enemyMoveset([Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT]);
|
||||||
|
await game.classicMode.startBattle([Species.MOLTRES]);
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
game.move.select(Moves.ROOST);
|
||||||
|
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||||
|
|
||||||
|
let playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes[0] === Type.FIRE).toBeTruthy();
|
||||||
|
expect(playerPokemonTypes.length === 1).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeTruthy();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
// Should be fire/flying/ghost
|
||||||
|
playerPokemonTypes = playerPokemon.getTypes();
|
||||||
|
expect(playerPokemonTypes.filter(type => type === Type.FLYING)).toHaveLength(1);
|
||||||
|
expect(playerPokemonTypes.filter(type => type === Type.FIRE)).toHaveLength(1);
|
||||||
|
expect(playerPokemonTypes.filter(type => type === Type.GHOST)).toHaveLength(1);
|
||||||
|
expect(playerPokemonTypes.length === 3).toBeTruthy();
|
||||||
|
expect(playerPokemon.isGrounded()).toBeFalsy();
|
||||||
|
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue