Compare commits
9 Commits
2b853bae25
...
c40717fd33
Author | SHA1 | Date | |
---|---|---|---|
|
c40717fd33 | ||
|
69c1389ec4 | ||
|
0e6c2952ca | ||
|
192aa63635 | ||
|
abced6cf02 | ||
|
5f6cb6ce00 | ||
|
0e92366cac | ||
|
8704723c9c | ||
|
5ede6a54c6 |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 6.2 KiB |
@ -2513,7 +2513,6 @@
|
|||||||
],
|
],
|
||||||
"meta": {
|
"meta": {
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
"app": "https://www.codeandweb.com/texturepacker",
|
||||||
"version": "3.0",
|
"version": "3.0"
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:edb2df3a947401efb05329a2c96d5d73:f256d83ef4df17c17958acc6e0432ab0:bad05b37c157676604256a043511a6a2$"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 318 B |
BIN
public/images/pokemon/icons/variant/2/177_2.png
Normal file
After Width: | Height: | Size: 271 B |
BIN
public/images/pokemon/icons/variant/2/177_3.png
Normal file
After Width: | Height: | Size: 271 B |
BIN
public/images/pokemon/icons/variant/2/178_2.png
Normal file
After Width: | Height: | Size: 318 B |
BIN
public/images/pokemon/icons/variant/2/178_3.png
Normal file
After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.2 KiB |
@ -3815,6 +3815,11 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
],
|
],
|
||||||
|
"178": [
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
"185": [
|
"185": [
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@ -7833,6 +7838,11 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
],
|
],
|
||||||
|
"178": [
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
"185": [
|
"185": [
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
|
BIN
public/images/pokemon/variant/back/177_2.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
public/images/pokemon/variant/back/177_3.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
2372
public/images/pokemon/variant/back/female/178_2.json
Normal file
BIN
public/images/pokemon/variant/back/female/178_2.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
2372
public/images/pokemon/variant/back/female/178_3.json
Normal file
BIN
public/images/pokemon/variant/back/female/178_3.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
2372
public/images/pokemon/variant/female/178_2.json
Normal file
BIN
public/images/pokemon/variant/female/178_2.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
2372
public/images/pokemon/variant/female/178_3.json
Normal file
BIN
public/images/pokemon/variant/female/178_3.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
@ -5,7 +5,7 @@ import Pokemon, { PlayerPokemon, EnemyPokemon } from "./field/pokemon";
|
|||||||
import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species";
|
import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species";
|
||||||
import { Constructor } from "#app/utils";
|
import { Constructor } from "#app/utils";
|
||||||
import * as Utils from "./utils";
|
import * as Utils from "./utils";
|
||||||
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems } from "./modifier/modifier";
|
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, TurnHeldItemTransferModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems } from "./modifier/modifier";
|
||||||
import { PokeballType } from "./data/pokeball";
|
import { PokeballType } from "./data/pokeball";
|
||||||
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims";
|
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims";
|
||||||
import { Phase } from "./phase";
|
import { Phase } from "./phase";
|
||||||
@ -37,7 +37,7 @@ import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin";
|
|||||||
import { addUiThemeOverrides } from "./ui/ui-theme";
|
import { addUiThemeOverrides } from "./ui/ui-theme";
|
||||||
import PokemonData from "./system/pokemon-data";
|
import PokemonData from "./system/pokemon-data";
|
||||||
import { Nature } from "./data/nature";
|
import { Nature } from "./data/nature";
|
||||||
import { SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger, pokemonFormChanges, FormChangeItem } from "./data/pokemon-forms";
|
import { SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger, pokemonFormChanges, FormChangeItem, SpeciesFormChange } from "./data/pokemon-forms";
|
||||||
import { FormChangePhase, QuietFormChangePhase } from "./form-change-phase";
|
import { FormChangePhase, QuietFormChangePhase } from "./form-change-phase";
|
||||||
import { getTypeRgb } from "./data/type";
|
import { getTypeRgb } from "./data/type";
|
||||||
import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler";
|
import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler";
|
||||||
@ -2579,7 +2579,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
// in case this is NECROZMA, determine which forms this
|
// in case this is NECROZMA, determine which forms this
|
||||||
const matchingFormChangeOpts = pokemonFormChanges[pokemon.species.speciesId].filter(fc => fc.findTrigger(formChangeTriggerType) && fc.canChange(pokemon));
|
const matchingFormChangeOpts = pokemonFormChanges[pokemon.species.speciesId].filter(fc => fc.findTrigger(formChangeTriggerType) && fc.canChange(pokemon));
|
||||||
let matchingFormChange;
|
let matchingFormChange: SpeciesFormChange | null;
|
||||||
if (pokemon.species.speciesId === Species.NECROZMA && matchingFormChangeOpts.length > 1) {
|
if (pokemon.species.speciesId === Species.NECROZMA && matchingFormChangeOpts.length > 1) {
|
||||||
// Ultra Necrozma is changing its form back, so we need to figure out into which form it devolves.
|
// Ultra Necrozma is changing its form back, so we need to figure out into which form it devolves.
|
||||||
const formChangeItemModifiers = (this.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[]).filter(m => m.active).map(m => m.formChangeItem);
|
const formChangeItemModifiers = (this.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[]).filter(m => m.active).map(m => m.formChangeItem);
|
||||||
@ -2666,7 +2666,9 @@ export default class BattleScene extends SceneBase {
|
|||||||
if (pokemon instanceof EnemyPokemon && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
if (pokemon instanceof EnemyPokemon && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
||||||
this.fadeOutBgm(Utils.fixedInt(2000), false);
|
this.fadeOutBgm(Utils.fixedInt(2000), false);
|
||||||
this.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin, pokemon.species.name, undefined, () => {
|
this.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin, pokemon.species.name, undefined, () => {
|
||||||
this.addEnemyModifier(getModifierType(modifierTypes.MINI_BLACK_HOLE).newModifier(pokemon) as PersistentModifier, false, true);
|
const finalBossMBH = getModifierType(modifierTypes.MINI_BLACK_HOLE).newModifier(pokemon) as TurnHeldItemTransferModifier;
|
||||||
|
finalBossMBH.setTransferrableFalse();
|
||||||
|
this.addEnemyModifier(finalBossMBH, false, true);
|
||||||
pokemon.generateAndPopulateMoveset(1);
|
pokemon.generateAndPopulateMoveset(1);
|
||||||
this.setFieldScale(0.75);
|
this.setFieldScale(0.75);
|
||||||
this.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
this.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
|
||||||
|
@ -5039,6 +5039,7 @@ export function initAbilities() {
|
|||||||
(pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }),
|
(pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }),
|
||||||
(pokemon) => Math.floor(pokemon.getMaxHp() / 8))
|
(pokemon) => Math.floor(pokemon.getMaxHp() / 8))
|
||||||
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
||||||
|
.bypassFaint()
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.BATTLE_BOND, 7)
|
new Ability(Abilities.BATTLE_BOND, 7)
|
||||||
.attr(PostVictoryFormChangeAbAttr, () => 2)
|
.attr(PostVictoryFormChangeAbAttr, () => 2)
|
||||||
@ -5191,6 +5192,7 @@ export function initAbilities() {
|
|||||||
.attr(FormBlockDamageAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
|
.attr(FormBlockDamageAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE,
|
||||||
(pokemon, abilityName) => i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }))
|
(pokemon, abilityName) => i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }))
|
||||||
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
||||||
|
.bypassFaint()
|
||||||
.ignorable(),
|
.ignorable(),
|
||||||
new Ability(Abilities.POWER_SPOT, 8)
|
new Ability(Abilities.POWER_SPOT, 8)
|
||||||
.attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3),
|
.attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3),
|
||||||
|
@ -837,6 +837,8 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
|||||||
new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)),
|
new SpeciesFormChange(Species.CRAMORANT, "", "gorging", new SpeciesFormChangeManualTrigger, true, new SpeciesFormChangeCondition(p => p.getHpRatio() < .5)),
|
||||||
new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeManualTrigger, true),
|
new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeManualTrigger, true),
|
||||||
new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeManualTrigger, true),
|
new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeManualTrigger, true),
|
||||||
|
new SpeciesFormChange(Species.CRAMORANT, "gulping", "", new SpeciesFormChangeActiveTrigger(false), true),
|
||||||
|
new SpeciesFormChange(Species.CRAMORANT, "gorging", "", new SpeciesFormChangeActiveTrigger(false), true),
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -922,7 +922,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
*/
|
*/
|
||||||
getLearnableLevelMoves(): Moves[] {
|
getLearnableLevelMoves(): Moves[] {
|
||||||
let levelMoves = this.getLevelMoves(1, true).map(lm => lm[1]);
|
let levelMoves = this.getLevelMoves(1, true).map(lm => lm[1]);
|
||||||
if (this.metBiome === -1 && !this.scene.gameMode.isFreshStartChallenge()) {
|
if (this.metBiome === -1 && !this.scene.gameMode.isFreshStartChallenge() && !this.scene.gameMode.isDaily) {
|
||||||
levelMoves = this.getUnlockedEggMoves().concat(levelMoves);
|
levelMoves = this.getUnlockedEggMoves().concat(levelMoves);
|
||||||
}
|
}
|
||||||
return levelMoves.filter(lm => !this.moveset.some(m => m?.moveId === lm));
|
return levelMoves.filter(lm => !this.moveset.some(m => m?.moveId === lm));
|
||||||
|
@ -62,7 +62,7 @@ export class GameMode implements GameModeConfig {
|
|||||||
* @returns true if the game mode has that challenge
|
* @returns true if the game mode has that challenge
|
||||||
*/
|
*/
|
||||||
hasChallenge(challenge: Challenges): boolean {
|
hasChallenge(challenge: Challenges): boolean {
|
||||||
return this.challenges.some(c => c.id === challenge);
|
return this.challenges.some(c => c.id === challenge && c.value !== 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2338,7 +2338,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
|||||||
* @see {@linkcode modifierTypes[MINI_BLACK_HOLE]}
|
* @see {@linkcode modifierTypes[MINI_BLACK_HOLE]}
|
||||||
*/
|
*/
|
||||||
export class TurnHeldItemTransferModifier extends HeldItemTransferModifier {
|
export class TurnHeldItemTransferModifier extends HeldItemTransferModifier {
|
||||||
readonly isTransferrable: boolean = true;
|
isTransferrable: boolean = true;
|
||||||
constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) {
|
constructor(type: ModifierType, pokemonId: integer, stackCount?: integer) {
|
||||||
super(type, pokemonId, stackCount);
|
super(type, pokemonId, stackCount);
|
||||||
}
|
}
|
||||||
@ -2362,6 +2362,10 @@ export class TurnHeldItemTransferModifier extends HeldItemTransferModifier {
|
|||||||
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
getMaxHeldItemCount(pokemon: Pokemon): integer {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTransferrableFalse(): void {
|
||||||
|
this.isTransferrable = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2034,7 +2034,8 @@ export class CommandPhase extends FieldPhase {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Command.BALL:
|
case Command.BALL:
|
||||||
if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || this.scene.gameMode.isFreshStartChallenge() || (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarters).length - 1))) {
|
const notInDex = (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarters).length - 1);
|
||||||
|
if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || this.scene.gameMode.isFreshStartChallenge() || notInDex )) {
|
||||||
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
|
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
|
||||||
this.scene.ui.setMode(Mode.MESSAGE);
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
this.scene.ui.showText(i18next.t("battle:noPokeballForce"), null, () => {
|
this.scene.ui.showText(i18next.t("battle:noPokeballForce"), null, () => {
|
||||||
|
@ -2,12 +2,12 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|||||||
import GameManager from "#test/utils/gameManager";
|
import GameManager from "#test/utils/gameManager";
|
||||||
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
import { Abilities } from "#enums/abilities";
|
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { StatusEffect } from "#app/data/status-effect.js";
|
import { StatusEffect } from "#app/data/status-effect.js";
|
||||||
import { MoveEffectPhase, MoveEndPhase, TurnEndPhase, TurnInitPhase } from "#app/phases.js";
|
import { CommandPhase, MoveEffectPhase, MoveEndPhase, TurnEndPhase, TurnInitPhase } from "#app/phases.js";
|
||||||
import { BattleStat } from "#app/data/battle-stat.js";
|
import { BattleStat } from "#app/data/battle-stat.js";
|
||||||
import { SPLASH_ONLY } from "../utils/testUtils";
|
import { SPLASH_ONLY } from "../utils/testUtils";
|
||||||
|
import { Mode } from "#app/ui/ui.js";
|
||||||
|
|
||||||
const TIMEOUT = 20 * 1000;
|
const TIMEOUT = 20 * 1000;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ describe("Abilities - Disguise", () => {
|
|||||||
game.override.moveset([Moves.SHADOW_SNEAK, Moves.VACUUM_WAVE, Moves.TOXIC_THREAD, Moves.SPLASH]);
|
game.override.moveset([Moves.SHADOW_SNEAK, Moves.VACUUM_WAVE, Moves.TOXIC_THREAD, Moves.SPLASH]);
|
||||||
}, TIMEOUT);
|
}, TIMEOUT);
|
||||||
|
|
||||||
it("takes no damage from attacking move and transforms to Busted form, taking 1/8 max HP damage from the disguise breaking", async () => {
|
it("takes no damage from attacking move and transforms to Busted form, takes 1/8 max HP damage from the disguise breaking", async () => {
|
||||||
await game.startBattle();
|
await game.startBattle();
|
||||||
|
|
||||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||||
@ -134,17 +134,30 @@ describe("Abilities - Disguise", () => {
|
|||||||
expect(mimikyu.formIndex).toBe(bustedForm);
|
expect(mimikyu.formIndex).toBe(bustedForm);
|
||||||
}, TIMEOUT);
|
}, TIMEOUT);
|
||||||
|
|
||||||
it("reverts to Disguised on arena reset", async () => {
|
it("persists form change when wave changes with no arena reset", async () => {
|
||||||
game.override.startingWave(4);
|
game.override.starterSpecies(0);
|
||||||
|
game.override.starterForms({
|
||||||
|
[Species.MIMIKYU]: bustedForm
|
||||||
|
});
|
||||||
|
await game.startBattle([Species.FURRET, Species.MIMIKYU]);
|
||||||
|
|
||||||
|
const mimikyu = game.scene.getParty()[1]!;
|
||||||
|
expect(mimikyu.formIndex).toBe(bustedForm);
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||||
|
await game.doKillOpponents();
|
||||||
|
await game.toNextWave();
|
||||||
|
|
||||||
|
expect(mimikyu.formIndex).toBe(bustedForm);
|
||||||
|
}, TIMEOUT);
|
||||||
|
|
||||||
|
it("reverts to Disguised form on arena reset", async () => {
|
||||||
|
game.override.startingWave(4);
|
||||||
game.override.starterSpecies(Species.MIMIKYU);
|
game.override.starterSpecies(Species.MIMIKYU);
|
||||||
game.override.starterForms({
|
game.override.starterForms({
|
||||||
[Species.MIMIKYU]: bustedForm
|
[Species.MIMIKYU]: bustedForm
|
||||||
});
|
});
|
||||||
|
|
||||||
game.override.enemySpecies(Species.MAGIKARP);
|
|
||||||
game.override.enemyAbility(Abilities.BALL_FETCH);
|
|
||||||
|
|
||||||
await game.startBattle();
|
await game.startBattle();
|
||||||
|
|
||||||
const mimikyu = game.scene.getPlayerPokemon()!;
|
const mimikyu = game.scene.getPlayerPokemon()!;
|
||||||
@ -153,10 +166,41 @@ describe("Abilities - Disguise", () => {
|
|||||||
|
|
||||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||||
await game.doKillOpponents();
|
await game.doKillOpponents();
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.toNextWave();
|
||||||
game.doSelectModifier();
|
|
||||||
await game.phaseInterceptor.to(TurnInitPhase);
|
|
||||||
|
|
||||||
expect(mimikyu.formIndex).toBe(disguisedForm);
|
expect(mimikyu.formIndex).toBe(disguisedForm);
|
||||||
}, TIMEOUT);
|
}, TIMEOUT);
|
||||||
|
|
||||||
|
it("reverts to Disguised form on biome change when fainted", async () => {
|
||||||
|
game.override.startingWave(10);
|
||||||
|
game.override.starterSpecies(0);
|
||||||
|
game.override.starterForms({
|
||||||
|
[Species.MIMIKYU]: bustedForm
|
||||||
|
});
|
||||||
|
|
||||||
|
await game.startBattle([Species.MIMIKYU, Species.FURRET]);
|
||||||
|
|
||||||
|
const mimikyu1 = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
expect(mimikyu1.formIndex).toBe(bustedForm);
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||||
|
await game.killPokemon(mimikyu1);
|
||||||
|
game.doSelectPartyPokemon(1);
|
||||||
|
await game.toNextTurn();
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||||
|
await game.doKillOpponents();
|
||||||
|
game.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { // TODO: Make tests run in set mode instead of switch mode
|
||||||
|
game.setMode(Mode.MESSAGE);
|
||||||
|
game.endPhase();
|
||||||
|
}, () => game.isCurrentPhase(CommandPhase) || game.isCurrentPhase(TurnInitPhase));
|
||||||
|
|
||||||
|
game.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
|
||||||
|
game.setMode(Mode.MESSAGE);
|
||||||
|
game.endPhase();
|
||||||
|
}, () => game.isCurrentPhase(CommandPhase) || game.isCurrentPhase(TurnInitPhase));
|
||||||
|
await game.phaseInterceptor.to("PartyHealPhase");
|
||||||
|
|
||||||
|
expect(mimikyu1.formIndex).toBe(disguisedForm);
|
||||||
|
}, TIMEOUT);
|
||||||
});
|
});
|
||||||
|
@ -84,6 +84,21 @@ describe("Abilities - Gulp Missile", () => {
|
|||||||
expect(cramorant.formIndex).toBe(GORGING_FORM);
|
expect(cramorant.formIndex).toBe(GORGING_FORM);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("changes to base form when switched out after Surf or Dive is used", async () => {
|
||||||
|
await game.startBattle([Species.CRAMORANT, Species.MAGIKARP]);
|
||||||
|
const cramorant = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.SURF));
|
||||||
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
game.doSwitchPokemon(1);
|
||||||
|
await game.toNextTurn(); // form change is delayed until after end of turn
|
||||||
|
|
||||||
|
expect(cramorant.formIndex).toBe(NORMAL_FORM);
|
||||||
|
expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_ARROKUDA)).toBeUndefined();
|
||||||
|
expect(cramorant.getTag(BattlerTagType.GULP_MISSILE_PIKACHU)).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("changes form during Dive's charge turn", async () => {
|
it("changes form during Dive's charge turn", async () => {
|
||||||
await game.startBattle([Species.CRAMORANT]);
|
await game.startBattle([Species.CRAMORANT]);
|
||||||
const cramorant = game.scene.getPlayerPokemon()!;
|
const cramorant = game.scene.getPlayerPokemon()!;
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
MovePhase,
|
MovePhase,
|
||||||
NewBattlePhase,
|
NewBattlePhase,
|
||||||
NextEncounterPhase,
|
NextEncounterPhase,
|
||||||
|
PartyHealPhase,
|
||||||
PostSummonPhase,
|
PostSummonPhase,
|
||||||
SelectGenderPhase,
|
SelectGenderPhase,
|
||||||
SelectModifierPhase,
|
SelectModifierPhase,
|
||||||
@ -92,6 +93,7 @@ export default class PhaseInterceptor {
|
|||||||
[QuietFormChangePhase, this.startPhase],
|
[QuietFormChangePhase, this.startPhase],
|
||||||
[SwitchPhase, this.startPhase],
|
[SwitchPhase, this.startPhase],
|
||||||
[SwitchSummonPhase, this.startPhase],
|
[SwitchSummonPhase, this.startPhase],
|
||||||
|
[PartyHealPhase, this.startPhase],
|
||||||
];
|
];
|
||||||
|
|
||||||
private endBySetMode = [
|
private endBySetMode = [
|
||||||
|
@ -2916,14 +2916,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
const isCaught = this.scene.gameData.dexData[species.speciesId]?.caughtAttr || BigInt(0);
|
const isCaught = this.scene.gameData.dexData[species.speciesId]?.caughtAttr || BigInt(0);
|
||||||
const isVariant3Caught = !!(isCaught & DexAttr.VARIANT_3);
|
const isVariant3Caught = !!(isCaught & DexAttr.VARIANT_3);
|
||||||
const isVariant2Caught = !!(isCaught & DexAttr.VARIANT_2);
|
const isVariant2Caught = !!(isCaught & DexAttr.VARIANT_2);
|
||||||
|
const isDefaultVariantCaught = !!(isCaught & DexAttr.DEFAULT_VARIANT);
|
||||||
const isVariantCaught = !!(isCaught & DexAttr.SHINY);
|
const isVariantCaught = !!(isCaught & DexAttr.SHINY);
|
||||||
const isMaleCaught = !!(isCaught & DexAttr.MALE);
|
const isMaleCaught = !!(isCaught & DexAttr.MALE);
|
||||||
const isFemaleCaught = !!(isCaught & DexAttr.FEMALE);
|
const isFemaleCaught = !!(isCaught & DexAttr.FEMALE);
|
||||||
|
|
||||||
if (!dexEntry.caughtAttr) {
|
const starterAttributes = this.starterPreferences[species.speciesId];
|
||||||
|
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId));
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId));
|
||||||
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||||
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
||||||
|
|
||||||
|
if (!dexEntry.caughtAttr) {
|
||||||
if (shiny === undefined || shiny !== props.shiny) {
|
if (shiny === undefined || shiny !== props.shiny) {
|
||||||
shiny = props.shiny;
|
shiny = props.shiny;
|
||||||
}
|
}
|
||||||
@ -2942,6 +2946,83 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
if (natureIndex === undefined || natureIndex !== defaultNature) {
|
if (natureIndex === undefined || natureIndex !== defaultNature) {
|
||||||
natureIndex = defaultNature;
|
natureIndex = defaultNature;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// compare current shiny, formIndex, female, variant, abilityIndex, natureIndex with the caught ones
|
||||||
|
// if the current ones are not caught, we need to find the next caught ones
|
||||||
|
if (shiny) {
|
||||||
|
if (!(isVariantCaught || isVariant2Caught || isVariant3Caught)) {
|
||||||
|
shiny = false;
|
||||||
|
starterAttributes.shiny = false;
|
||||||
|
variant = 0;
|
||||||
|
starterAttributes.variant = 0;
|
||||||
|
} else {
|
||||||
|
shiny = true;
|
||||||
|
starterAttributes.shiny = true;
|
||||||
|
if (variant === 0 && !isDefaultVariantCaught) {
|
||||||
|
if (isVariant2Caught) {
|
||||||
|
variant = 1;
|
||||||
|
starterAttributes.variant = 1;
|
||||||
|
} else if (isVariant3Caught) {
|
||||||
|
variant = 2;
|
||||||
|
starterAttributes.variant = 2;
|
||||||
|
} else {
|
||||||
|
variant = 0;
|
||||||
|
starterAttributes.variant = 0;
|
||||||
|
}
|
||||||
|
} else if (variant === 1 && !isVariant2Caught) {
|
||||||
|
if (isVariantCaught) {
|
||||||
|
variant = 0;
|
||||||
|
starterAttributes.variant = 0;
|
||||||
|
} else if (isVariant3Caught) {
|
||||||
|
variant = 2;
|
||||||
|
starterAttributes.variant = 2;
|
||||||
|
} else {
|
||||||
|
variant = 0;
|
||||||
|
starterAttributes.variant = 0;
|
||||||
|
}
|
||||||
|
} else if (variant === 2 && !isVariant3Caught) {
|
||||||
|
if (isVariantCaught) {
|
||||||
|
variant = 0;
|
||||||
|
starterAttributes.variant = 0;
|
||||||
|
} else if (isVariant2Caught) {
|
||||||
|
variant = 1;
|
||||||
|
starterAttributes.variant = 1;
|
||||||
|
} else {
|
||||||
|
variant = 0;
|
||||||
|
starterAttributes.variant = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (female) {
|
||||||
|
if (!isFemaleCaught) {
|
||||||
|
female = false;
|
||||||
|
starterAttributes.female = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isMaleCaught) {
|
||||||
|
female = true;
|
||||||
|
starterAttributes.female = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (species.forms) {
|
||||||
|
const formCount = species.forms.length;
|
||||||
|
let newFormIndex = formIndex??0;
|
||||||
|
if (species.forms[newFormIndex]) {
|
||||||
|
const isValidForm = species.forms[newFormIndex].isStarterSelectable && dexEntry.caughtAttr & this.scene.gameData.getFormAttr(newFormIndex);
|
||||||
|
if (!isValidForm) {
|
||||||
|
do {
|
||||||
|
newFormIndex = (newFormIndex + 1) % formCount;
|
||||||
|
if (species.forms[newFormIndex].isStarterSelectable && dexEntry.caughtAttr & this.scene.gameData.getFormAttr(newFormIndex)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (newFormIndex !== props.formIndex);
|
||||||
|
formIndex = newFormIndex;
|
||||||
|
starterAttributes.form = formIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shinyOverlay.setVisible(shiny ?? false); // TODO: is false the correct default?
|
this.shinyOverlay.setVisible(shiny ?? false); // TODO: is false the correct default?
|
||||||
@ -2993,12 +3074,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dexEntry.caughtAttr && species.malePercent !== null) {
|
if (dexEntry.caughtAttr && species.malePercent !== null) {
|
||||||
let gender: Gender;
|
const gender = !female ? Gender.MALE : Gender.FEMALE;
|
||||||
if ((female && isFemaleCaught) || (!female && !isMaleCaught)) {
|
|
||||||
gender = Gender.FEMALE;
|
|
||||||
} else {
|
|
||||||
gender = Gender.MALE;
|
|
||||||
}
|
|
||||||
this.pokemonGenderText.setText(getGenderSymbol(gender));
|
this.pokemonGenderText.setText(getGenderSymbol(gender));
|
||||||
this.pokemonGenderText.setColor(getGenderColor(gender));
|
this.pokemonGenderText.setColor(getGenderColor(gender));
|
||||||
this.pokemonGenderText.setShadowColor(getGenderColor(gender, true));
|
this.pokemonGenderText.setShadowColor(getGenderColor(gender, true));
|
||||||
@ -3479,7 +3555,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
checkIconId(icon: Phaser.GameObjects.Sprite, species: PokemonSpecies, female: boolean, formIndex: number, shiny: boolean, variant: number) {
|
checkIconId(icon: Phaser.GameObjects.Sprite, species: PokemonSpecies, female: boolean, formIndex: number, shiny: boolean, variant: number) {
|
||||||
if (icon.frame.name !== species.getIconId(female, formIndex, shiny, variant)) {
|
if (icon.frame.name !== species.getIconId(female, formIndex, shiny, variant)) {
|
||||||
console.log(`${species.name}'s variant icon does not exist. Replacing with default.`);
|
console.log(`${species.name}'s icon ${icon.frame.name} does not match getIconId with female: ${female}, formIndex: ${formIndex}, shiny: ${shiny}, variant: ${variant}`);
|
||||||
icon.setTexture(species.getIconAtlasKey(formIndex, false, variant));
|
icon.setTexture(species.getIconAtlasKey(formIndex, false, variant));
|
||||||
icon.setFrame(species.getIconId(female, formIndex, false, variant));
|
icon.setFrame(species.getIconId(female, formIndex, false, variant));
|
||||||
}
|
}
|
||||||
|