mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-20 22:39:31 +02:00
Merge branch 'beta' into ability/wimpout
This commit is contained in:
commit
075a14b9cf
108
src/data/move.ts
108
src/data/move.ts
@ -5871,7 +5871,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class ChillyReceptionAttr extends ForceSwitchOutAttr {
|
export class ChillyReceptionAttr extends ForceSwitchOutAttr {
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
user.scene.arena.trySetWeather(WeatherType.SNOW, true);
|
user.scene.arena.trySetWeather(WeatherType.SNOW, true);
|
||||||
@ -5958,15 +5957,107 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const biomeType = user.scene.arena.getTypeForBiome();
|
const terrainType = user.scene.arena.getTerrainType();
|
||||||
|
let typeChange: Type;
|
||||||
|
if (terrainType !== TerrainType.NONE) {
|
||||||
|
typeChange = this.getTypeForTerrain(user.scene.arena.getTerrainType());
|
||||||
|
} else {
|
||||||
|
typeChange = this.getTypeForBiome(user.scene.arena.biomeType);
|
||||||
|
}
|
||||||
|
|
||||||
user.summonData.types = [ biomeType ];
|
user.summonData.types = [ typeChange ];
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${Type[biomeType]}`) }));
|
user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${Type[typeChange]}`) }));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a type from the current terrain
|
||||||
|
* @param terrainType {@linkcode TerrainType}
|
||||||
|
* @returns {@linkcode Type}
|
||||||
|
*/
|
||||||
|
private getTypeForTerrain(terrainType: TerrainType): Type {
|
||||||
|
switch (terrainType) {
|
||||||
|
case TerrainType.ELECTRIC:
|
||||||
|
return Type.ELECTRIC;
|
||||||
|
case TerrainType.MISTY:
|
||||||
|
return Type.FAIRY;
|
||||||
|
case TerrainType.GRASSY:
|
||||||
|
return Type.GRASS;
|
||||||
|
case TerrainType.PSYCHIC:
|
||||||
|
return Type.PSYCHIC;
|
||||||
|
case TerrainType.NONE:
|
||||||
|
default:
|
||||||
|
return Type.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a type from the current biome
|
||||||
|
* @param biomeType {@linkcode Biome}
|
||||||
|
* @returns {@linkcode Type}
|
||||||
|
*/
|
||||||
|
private getTypeForBiome(biomeType: Biome): Type {
|
||||||
|
switch (biomeType) {
|
||||||
|
case Biome.TOWN:
|
||||||
|
case Biome.PLAINS:
|
||||||
|
case Biome.METROPOLIS:
|
||||||
|
return Type.NORMAL;
|
||||||
|
case Biome.GRASS:
|
||||||
|
case Biome.TALL_GRASS:
|
||||||
|
return Type.GRASS;
|
||||||
|
case Biome.FOREST:
|
||||||
|
case Biome.JUNGLE:
|
||||||
|
return Type.BUG;
|
||||||
|
case Biome.SLUM:
|
||||||
|
case Biome.SWAMP:
|
||||||
|
return Type.POISON;
|
||||||
|
case Biome.SEA:
|
||||||
|
case Biome.BEACH:
|
||||||
|
case Biome.LAKE:
|
||||||
|
case Biome.SEABED:
|
||||||
|
return Type.WATER;
|
||||||
|
case Biome.MOUNTAIN:
|
||||||
|
return Type.FLYING;
|
||||||
|
case Biome.BADLANDS:
|
||||||
|
return Type.GROUND;
|
||||||
|
case Biome.CAVE:
|
||||||
|
case Biome.DESERT:
|
||||||
|
return Type.ROCK;
|
||||||
|
case Biome.ICE_CAVE:
|
||||||
|
case Biome.SNOWY_FOREST:
|
||||||
|
return Type.ICE;
|
||||||
|
case Biome.MEADOW:
|
||||||
|
case Biome.FAIRY_CAVE:
|
||||||
|
case Biome.ISLAND:
|
||||||
|
return Type.FAIRY;
|
||||||
|
case Biome.POWER_PLANT:
|
||||||
|
return Type.ELECTRIC;
|
||||||
|
case Biome.VOLCANO:
|
||||||
|
return Type.FIRE;
|
||||||
|
case Biome.GRAVEYARD:
|
||||||
|
case Biome.TEMPLE:
|
||||||
|
return Type.GHOST;
|
||||||
|
case Biome.DOJO:
|
||||||
|
case Biome.CONSTRUCTION_SITE:
|
||||||
|
return Type.FIGHTING;
|
||||||
|
case Biome.FACTORY:
|
||||||
|
case Biome.LABORATORY:
|
||||||
|
return Type.STEEL;
|
||||||
|
case Biome.RUINS:
|
||||||
|
case Biome.SPACE:
|
||||||
|
return Type.PSYCHIC;
|
||||||
|
case Biome.WASTELAND:
|
||||||
|
case Biome.END:
|
||||||
|
return Type.DRAGON;
|
||||||
|
case Biome.ABYSS:
|
||||||
|
return Type.DARK;
|
||||||
|
default:
|
||||||
|
return Type.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeTypeAttr extends MoveEffectAttr {
|
export class ChangeTypeAttr extends MoveEffectAttr {
|
||||||
@ -7095,6 +7186,11 @@ const targetSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target
|
|||||||
|
|
||||||
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => user.scene.phaseQueue.find(phase => phase instanceof MovePhase) !== undefined;
|
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => user.scene.phaseQueue.find(phase => phase instanceof MovePhase) !== undefined;
|
||||||
|
|
||||||
|
const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => {
|
||||||
|
const party: Pokemon[] = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty();
|
||||||
|
return party.some(pokemon => pokemon.isActive() && !pokemon.isOnField());
|
||||||
|
};
|
||||||
|
|
||||||
export type MoveAttrFilter = (attr: MoveAttr) => boolean;
|
export type MoveAttrFilter = (attr: MoveAttr) => boolean;
|
||||||
|
|
||||||
function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon | null, target: Pokemon | null, move: Move, args: any[]): Promise<void> {
|
function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon | null, target: Pokemon | null, move: Move, args: any[]): Promise<void> {
|
||||||
@ -8004,6 +8100,7 @@ export function initMoves() {
|
|||||||
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
|
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
|
||||||
new SelfStatusMove(Moves.BATON_PASS, Type.NORMAL, -1, 40, -1, 0, 2)
|
new SelfStatusMove(Moves.BATON_PASS, Type.NORMAL, -1, 40, -1, 0, 2)
|
||||||
.attr(ForceSwitchOutAttr, true, SwitchType.BATON_PASS)
|
.attr(ForceSwitchOutAttr, true, SwitchType.BATON_PASS)
|
||||||
|
.condition(failIfLastInPartyCondition)
|
||||||
.hidesUser(),
|
.hidesUser(),
|
||||||
new StatusMove(Moves.ENCORE, Type.NORMAL, 100, 5, -1, 0, 2)
|
new StatusMove(Moves.ENCORE, Type.NORMAL, 100, 5, -1, 0, 2)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.ENCORE, false, true)
|
.attr(AddBattlerTagAttr, BattlerTagType.ENCORE, false, true)
|
||||||
@ -10144,7 +10241,8 @@ export function initMoves() {
|
|||||||
.makesContact(),
|
.makesContact(),
|
||||||
new SelfStatusMove(Moves.SHED_TAIL, Type.NORMAL, -1, 10, -1, 0, 9)
|
new SelfStatusMove(Moves.SHED_TAIL, Type.NORMAL, -1, 10, -1, 0, 9)
|
||||||
.attr(AddSubstituteAttr, 0.5)
|
.attr(AddSubstituteAttr, 0.5)
|
||||||
.attr(ForceSwitchOutAttr, true, SwitchType.SHED_TAIL),
|
.attr(ForceSwitchOutAttr, true, SwitchType.SHED_TAIL)
|
||||||
|
.condition(failIfLastInPartyCondition),
|
||||||
new SelfStatusMove(Moves.CHILLY_RECEPTION, Type.ICE, -1, 10, -1, 0, 9)
|
new SelfStatusMove(Moves.CHILLY_RECEPTION, Type.ICE, -1, 10, -1, 0, 9)
|
||||||
.attr(PreMoveMessageAttr, (user, move) => i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(user) }))
|
.attr(PreMoveMessageAttr, (user, move) => i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(user) }))
|
||||||
.attr(ChillyReceptionAttr, true),
|
.attr(ChillyReceptionAttr, true),
|
||||||
|
@ -224,66 +224,6 @@ export class Arena {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTypeForBiome() {
|
|
||||||
switch (this.biomeType) {
|
|
||||||
case Biome.TOWN:
|
|
||||||
case Biome.PLAINS:
|
|
||||||
case Biome.METROPOLIS:
|
|
||||||
return Type.NORMAL;
|
|
||||||
case Biome.GRASS:
|
|
||||||
case Biome.TALL_GRASS:
|
|
||||||
return Type.GRASS;
|
|
||||||
case Biome.FOREST:
|
|
||||||
case Biome.JUNGLE:
|
|
||||||
return Type.BUG;
|
|
||||||
case Biome.SLUM:
|
|
||||||
case Biome.SWAMP:
|
|
||||||
return Type.POISON;
|
|
||||||
case Biome.SEA:
|
|
||||||
case Biome.BEACH:
|
|
||||||
case Biome.LAKE:
|
|
||||||
case Biome.SEABED:
|
|
||||||
return Type.WATER;
|
|
||||||
case Biome.MOUNTAIN:
|
|
||||||
return Type.FLYING;
|
|
||||||
case Biome.BADLANDS:
|
|
||||||
return Type.GROUND;
|
|
||||||
case Biome.CAVE:
|
|
||||||
case Biome.DESERT:
|
|
||||||
return Type.ROCK;
|
|
||||||
case Biome.ICE_CAVE:
|
|
||||||
case Biome.SNOWY_FOREST:
|
|
||||||
return Type.ICE;
|
|
||||||
case Biome.MEADOW:
|
|
||||||
case Biome.FAIRY_CAVE:
|
|
||||||
case Biome.ISLAND:
|
|
||||||
return Type.FAIRY;
|
|
||||||
case Biome.POWER_PLANT:
|
|
||||||
return Type.ELECTRIC;
|
|
||||||
case Biome.VOLCANO:
|
|
||||||
return Type.FIRE;
|
|
||||||
case Biome.GRAVEYARD:
|
|
||||||
case Biome.TEMPLE:
|
|
||||||
return Type.GHOST;
|
|
||||||
case Biome.DOJO:
|
|
||||||
case Biome.CONSTRUCTION_SITE:
|
|
||||||
return Type.FIGHTING;
|
|
||||||
case Biome.FACTORY:
|
|
||||||
case Biome.LABORATORY:
|
|
||||||
return Type.STEEL;
|
|
||||||
case Biome.RUINS:
|
|
||||||
case Biome.SPACE:
|
|
||||||
return Type.PSYCHIC;
|
|
||||||
case Biome.WASTELAND:
|
|
||||||
case Biome.END:
|
|
||||||
return Type.DRAGON;
|
|
||||||
case Biome.ABYSS:
|
|
||||||
return Type.DARK;
|
|
||||||
default:
|
|
||||||
return Type.UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getBgTerrainColorRatioForBiome(): number {
|
getBgTerrainColorRatioForBiome(): number {
|
||||||
switch (this.biomeType) {
|
switch (this.biomeType) {
|
||||||
case Biome.SPACE:
|
case Biome.SPACE:
|
||||||
|
49
src/test/moves/camouflage.test.ts
Normal file
49
src/test/moves/camouflage.test.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { TerrainType } from "#app/data/terrain";
|
||||||
|
import { Type } from "#app/data/type";
|
||||||
|
import { BattlerIndex } from "#app/battle";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("Moves - Camouflage", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.moveset([ Moves.CAMOUFLAGE ])
|
||||||
|
.ability(Abilities.BALL_FETCH)
|
||||||
|
.battleType("single")
|
||||||
|
.disableCrits()
|
||||||
|
.enemySpecies(Species.REGIELEKI)
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.enemyMoveset(Moves.PSYCHIC_TERRAIN);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Camouflage should look at terrain first when selecting a type to change into", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.SHUCKLE ]);
|
||||||
|
|
||||||
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
game.move.select(Moves.CAMOUFLAGE);
|
||||||
|
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
expect(game.scene.arena.getTerrainType()).toBe(TerrainType.PSYCHIC);
|
||||||
|
const pokemonType = playerPokemon.getTypes()[0];
|
||||||
|
expect(pokemonType).toBe(Type.PSYCHIC);
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,5 @@
|
|||||||
import { SubstituteTag } from "#app/data/battler-tags";
|
import { SubstituteTag } from "#app/data/battler-tags";
|
||||||
|
import { MoveResult } from "#app/field/pokemon";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
@ -53,4 +54,18 @@ describe("Moves - Shed Tail", () => {
|
|||||||
expect(substituteTag).toBeDefined();
|
expect(substituteTag).toBeDefined();
|
||||||
expect(substituteTag?.hp).toBe(Math.floor(magikarp.getMaxHp() / 4));
|
expect(substituteTag?.hp).toBe(Math.floor(magikarp.getMaxHp() / 4));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should fail if no ally is available to switch in", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const magikarp = game.scene.getPlayerPokemon()!;
|
||||||
|
expect(game.scene.getParty().length).toBe(1);
|
||||||
|
|
||||||
|
game.move.select(Moves.SHED_TAIL);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to("TurnEndPhase", false);
|
||||||
|
|
||||||
|
expect(magikarp.isOnField()).toBeTruthy();
|
||||||
|
expect(magikarp.getLastXMoves()[0].result).toBe(MoveResult.FAIL);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user