mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-29 19:52:27 +02:00
Compare commits
7 Commits
9eb57c0c66
...
15106b83fb
Author | SHA1 | Date | |
---|---|---|---|
|
15106b83fb | ||
|
b4a891cc71 | ||
|
b5a40bfdfc | ||
|
f0d4dfa09e | ||
|
49bb681554 | ||
|
aaad2241ae | ||
|
cff3adf2e6 |
@ -13,6 +13,7 @@
|
|||||||
"test:cov": "vitest run --project pre && vitest run --project main --coverage",
|
"test:cov": "vitest run --project pre && vitest run --project main --coverage",
|
||||||
"test:watch": "vitest run --project pre && vitest watch --project main --coverage",
|
"test:watch": "vitest run --project pre && vitest watch --project main --coverage",
|
||||||
"test:silent": "vitest run --project pre && vitest run --project main --silent",
|
"test:silent": "vitest run --project pre && vitest run --project main --silent",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
"eslint": "eslint --fix .",
|
"eslint": "eslint --fix .",
|
||||||
"eslint-ci": "eslint .",
|
"eslint-ci": "eslint .",
|
||||||
"docs": "typedoc",
|
"docs": "typedoc",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//import { battleAnimRawData } from "./battle-anim-raw-data";
|
//import { battleAnimRawData } from "./battle-anim-raw-data";
|
||||||
import BattleScene from "../battle-scene";
|
import BattleScene from "../battle-scene";
|
||||||
import { AttackMove, ChargeAttr, DelayedAttackAttr, MoveFlags, SelfStatusMove, allMoves } from "./move";
|
import { AttackMove, BeakBlastHeaderAttr, ChargeAttr, DelayedAttackAttr, MoveFlags, SelfStatusMove, allMoves } from "./move";
|
||||||
import Pokemon from "../field/pokemon";
|
import Pokemon from "../field/pokemon";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import { BattlerIndex } from "../battle";
|
import { BattlerIndex } from "../battle";
|
||||||
@ -499,7 +499,9 @@ export function initMoveAnim(scene: BattleScene, move: Moves): Promise<void> {
|
|||||||
} else {
|
} else {
|
||||||
populateMoveAnim(move, ba);
|
populateMoveAnim(move, ba);
|
||||||
}
|
}
|
||||||
const chargeAttr = allMoves[move].getAttrs(ChargeAttr)[0] || allMoves[move].getAttrs(DelayedAttackAttr)[0];
|
const chargeAttr = allMoves[move].getAttrs(ChargeAttr)[0]
|
||||||
|
|| allMoves[move].getAttrs(DelayedAttackAttr)[0]
|
||||||
|
|| allMoves[move].getAttrs(BeakBlastHeaderAttr)[0];
|
||||||
if (chargeAttr) {
|
if (chargeAttr) {
|
||||||
initMoveChargeAnim(scene, chargeAttr.chargeAnim).then(() => resolve());
|
initMoveChargeAnim(scene, chargeAttr.chargeAnim).then(() => resolve());
|
||||||
} else {
|
} else {
|
||||||
@ -570,7 +572,9 @@ export function loadMoveAnimAssets(scene: BattleScene, moveIds: Moves[], startLo
|
|||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const moveAnimations = moveIds.map(m => moveAnims.get(m) as AnimConfig).flat();
|
const moveAnimations = moveIds.map(m => moveAnims.get(m) as AnimConfig).flat();
|
||||||
for (const moveId of moveIds) {
|
for (const moveId of moveIds) {
|
||||||
const chargeAttr = allMoves[moveId].getAttrs(ChargeAttr)[0] || allMoves[moveId].getAttrs(DelayedAttackAttr)[0];
|
const chargeAttr = allMoves[moveId].getAttrs(ChargeAttr)[0]
|
||||||
|
|| allMoves[moveId].getAttrs(DelayedAttackAttr)[0]
|
||||||
|
|| allMoves[moveId].getAttrs(BeakBlastHeaderAttr)[0];
|
||||||
if (chargeAttr) {
|
if (chargeAttr) {
|
||||||
const moveChargeAnims = chargeAnims.get(chargeAttr.chargeAnim);
|
const moveChargeAnims = chargeAnims.get(chargeAttr.chargeAnim);
|
||||||
moveAnimations.push(moveChargeAnims instanceof AnimConfig ? moveChargeAnims : moveChargeAnims![0]); // TODO: is the bang correct?
|
moveAnimations.push(moveChargeAnims instanceof AnimConfig ? moveChargeAnims : moveChargeAnims![0]); // TODO: is the bang correct?
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
|
import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveChargeAnim } from "./battle-anims";
|
||||||
import { CommonAnimPhase, MoveEffectPhase, MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangeCallback, StatChangePhase } from "../phases";
|
import { CommonAnimPhase, MoveEffectPhase, MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangeCallback, StatChangePhase } from "../phases";
|
||||||
import { getPokemonNameWithAffix } from "../messages";
|
import { getPokemonNameWithAffix } from "../messages";
|
||||||
import Pokemon, { MoveResult, HitResult } from "../field/pokemon";
|
import Pokemon, { MoveResult, HitResult } from "../field/pokemon";
|
||||||
@ -118,6 +118,44 @@ export class RechargingTag extends BattlerTag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BattlerTag representing the "charge phase" of Beak Blast
|
||||||
|
* Pokemon with this tag will inflict BURN status on any attacker that makes contact.
|
||||||
|
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Beak_Blast_(move) | Beak Blast}
|
||||||
|
*/
|
||||||
|
export class BeakBlastChargingTag extends BattlerTag {
|
||||||
|
constructor() {
|
||||||
|
super(BattlerTagType.BEAK_BLAST_CHARGING, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END ], 1, Moves.BEAK_BLAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd(pokemon: Pokemon): void {
|
||||||
|
// Play Beak Blast's charging animation
|
||||||
|
new MoveChargeAnim(ChargeAnim.BEAK_BLAST_CHARGING, this.sourceMove, pokemon).play(pokemon.scene);
|
||||||
|
|
||||||
|
// Queue Beak Blast's header message
|
||||||
|
pokemon.scene.queueMessage(i18next.t("moveTriggers:startedHeatingUpBeak", { pokemonName: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inflicts `BURN` status on attackers that make contact, and causes this tag
|
||||||
|
* to be removed after the source makes a move (or the turn ends, whichever comes first)
|
||||||
|
* @param pokemon {@linkcode Pokemon} the owner of this tag
|
||||||
|
* @param lapseType {@linkcode BattlerTagLapseType} the type of functionality invoked in battle
|
||||||
|
* @returns `true` if invoked with the CUSTOM lapse type; `false` otherwise
|
||||||
|
*/
|
||||||
|
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
|
if (lapseType === BattlerTagLapseType.CUSTOM) {
|
||||||
|
const effectPhase = pokemon.scene.getCurrentPhase();
|
||||||
|
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) {
|
||||||
|
const attacker = effectPhase.getPokemon();
|
||||||
|
attacker.trySetStatus(StatusEffect.BURN, true, pokemon);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.lapse(pokemon, lapseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class TrappedTag extends BattlerTag {
|
export class TrappedTag extends BattlerTag {
|
||||||
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) {
|
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: number, sourceMove: Moves, sourceId: number) {
|
||||||
super(tagType, lapseType, turnCount, sourceMove, sourceId);
|
super(tagType, lapseType, turnCount, sourceMove, sourceId);
|
||||||
@ -1738,6 +1776,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
|
|||||||
switch (tagType) {
|
switch (tagType) {
|
||||||
case BattlerTagType.RECHARGING:
|
case BattlerTagType.RECHARGING:
|
||||||
return new RechargingTag(sourceMove);
|
return new RechargingTag(sourceMove);
|
||||||
|
case BattlerTagType.BEAK_BLAST_CHARGING:
|
||||||
|
return new BeakBlastChargingTag();
|
||||||
case BattlerTagType.FLINCHED:
|
case BattlerTagType.FLINCHED:
|
||||||
return new FlinchedTag(sourceMove);
|
return new FlinchedTag(sourceMove);
|
||||||
case BattlerTagType.INTERRUPTED:
|
case BattlerTagType.INTERRUPTED:
|
||||||
|
@ -273,11 +273,9 @@ export abstract class Challenge {
|
|||||||
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
|
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
|
||||||
* @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon.
|
* @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon.
|
||||||
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
||||||
* @param checkEvolutions {@link boolean} If true, check the pokemon's future evolutions
|
|
||||||
* @param checkForms {@link boolean} If true, check the pokemon's alternative forms
|
|
||||||
* @returns {@link boolean} Whether this function did anything.
|
* @returns {@link boolean} Whether this function did anything.
|
||||||
*/
|
*/
|
||||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean, checkForms?: boolean): boolean {
|
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,14 +403,13 @@ export class SingleGenerationChallenge extends Challenge {
|
|||||||
super(Challenges.SINGLE_GENERATION, 9);
|
super(Challenges.SINGLE_GENERATION, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean): boolean {
|
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||||
const generations = [pokemon.generation];
|
const generations = [pokemon.generation];
|
||||||
const checkPokemonEvolutions = checkEvolutions ?? true as boolean;
|
|
||||||
if (soft) {
|
if (soft) {
|
||||||
const speciesToCheck = [pokemon.speciesId];
|
const speciesToCheck = [pokemon.speciesId];
|
||||||
while (speciesToCheck.length) {
|
while (speciesToCheck.length) {
|
||||||
const checking = speciesToCheck.pop();
|
const checking = speciesToCheck.pop();
|
||||||
if (checking && pokemonEvolutions.hasOwnProperty(checking) && checkPokemonEvolutions) {
|
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||||
pokemonEvolutions[checking].forEach(e => {
|
pokemonEvolutions[checking].forEach(e => {
|
||||||
speciesToCheck.push(e.speciesId);
|
speciesToCheck.push(e.speciesId);
|
||||||
generations.push(getPokemonSpecies(e.speciesId).generation);
|
generations.push(getPokemonSpecies(e.speciesId).generation);
|
||||||
@ -533,22 +530,20 @@ export class SingleTypeChallenge extends Challenge {
|
|||||||
super(Challenges.SINGLE_TYPE, 18);
|
super(Challenges.SINGLE_TYPE, 18);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean, checkForms?: boolean): boolean {
|
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||||
const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex);
|
const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex);
|
||||||
const types = [speciesForm.type1, speciesForm.type2];
|
const types = [speciesForm.type1, speciesForm.type2];
|
||||||
const checkPokemonEvolutions = checkEvolutions ?? true as boolean;
|
|
||||||
const checkPokemonForms = checkForms ?? true as boolean;
|
|
||||||
if (soft) {
|
if (soft) {
|
||||||
const speciesToCheck = [pokemon.speciesId];
|
const speciesToCheck = [pokemon.speciesId];
|
||||||
while (speciesToCheck.length) {
|
while (speciesToCheck.length) {
|
||||||
const checking = speciesToCheck.pop();
|
const checking = speciesToCheck.pop();
|
||||||
if (checking && pokemonEvolutions.hasOwnProperty(checking) && checkPokemonEvolutions) {
|
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||||
pokemonEvolutions[checking].forEach(e => {
|
pokemonEvolutions[checking].forEach(e => {
|
||||||
speciesToCheck.push(e.speciesId);
|
speciesToCheck.push(e.speciesId);
|
||||||
types.push(getPokemonSpecies(e.speciesId).type1, getPokemonSpecies(e.speciesId).type2);
|
types.push(getPokemonSpecies(e.speciesId).type1, getPokemonSpecies(e.speciesId).type2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (checking && pokemonFormChanges.hasOwnProperty(checking) && checkPokemonForms) {
|
if (checking && pokemonFormChanges.hasOwnProperty(checking)) {
|
||||||
pokemonFormChanges[checking].forEach(f1 => {
|
pokemonFormChanges[checking].forEach(f1 => {
|
||||||
getPokemonSpecies(checking).forms.forEach(f2 => {
|
getPokemonSpecies(checking).forms.forEach(f2 => {
|
||||||
if (f1.formKey === f2.formKey) {
|
if (f1.formKey === f2.formKey) {
|
||||||
@ -746,7 +741,7 @@ export class LowerStarterPointsChallenge extends Challenge {
|
|||||||
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
||||||
* @returns True if any challenge was successfully applied.
|
* @returns True if any challenge was successfully applied.
|
||||||
*/
|
*/
|
||||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean, checkEvolutions?: boolean, checkForms?: boolean): boolean;
|
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean): boolean;
|
||||||
/**
|
/**
|
||||||
* Apply all challenges that modify available total starter points.
|
* Apply all challenges that modify available total starter points.
|
||||||
* @param gameMode {@link GameMode} The current gameMode
|
* @param gameMode {@link GameMode} The current gameMode
|
||||||
@ -854,7 +849,7 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
|||||||
if (c.value !== 0) {
|
if (c.value !== 0) {
|
||||||
switch (challengeType) {
|
switch (challengeType) {
|
||||||
case ChallengeType.STARTER_CHOICE:
|
case ChallengeType.STARTER_CHOICE:
|
||||||
ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3], args[4], args[5]);
|
ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]);
|
||||||
break;
|
break;
|
||||||
case ChallengeType.STARTER_POINTS:
|
case ChallengeType.STARTER_POINTS:
|
||||||
ret ||= c.applyStarterPoints(args[0]);
|
ret ||= c.applyStarterPoints(args[0]);
|
||||||
|
@ -1021,6 +1021,22 @@ export class MessageHeaderAttr extends MoveHeaderAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header attribute to implement the "charge phase" of Beak Blast at the
|
||||||
|
* beginning of a turn.
|
||||||
|
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Beak_Blast_(move) | Beak Blast}
|
||||||
|
* @see {@linkcode BeakBlastChargingTag}
|
||||||
|
*/
|
||||||
|
export class BeakBlastHeaderAttr extends MoveHeaderAttr {
|
||||||
|
/** Required to initialize Beak Blast's charge animation correctly */
|
||||||
|
public chargeAnim = ChargeAnim.BEAK_BLAST_CHARGING;
|
||||||
|
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
user.addTag(BattlerTagType.BEAK_BLAST_CHARGING);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PreMoveMessageAttr extends MoveAttr {
|
export class PreMoveMessageAttr extends MoveAttr {
|
||||||
private message: string | ((user: Pokemon, target: Pokemon, move: Move) => string);
|
private message: string | ((user: Pokemon, target: Pokemon, move: Move) => string);
|
||||||
|
|
||||||
@ -2391,24 +2407,21 @@ export class ChargeAttr extends OverrideMoveEffectAttr {
|
|||||||
private chargeText: string;
|
private chargeText: string;
|
||||||
private tagType: BattlerTagType | null;
|
private tagType: BattlerTagType | null;
|
||||||
private chargeEffect: boolean;
|
private chargeEffect: boolean;
|
||||||
public sameTurn: boolean;
|
|
||||||
public followUpPriority: integer | null;
|
public followUpPriority: integer | null;
|
||||||
|
|
||||||
constructor(chargeAnim: ChargeAnim, chargeText: string, tagType?: BattlerTagType | null, chargeEffect: boolean = false, sameTurn: boolean = false, followUpPriority?: integer) {
|
constructor(chargeAnim: ChargeAnim, chargeText: string, tagType?: BattlerTagType | null, chargeEffect: boolean = false) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.chargeAnim = chargeAnim;
|
this.chargeAnim = chargeAnim;
|
||||||
this.chargeText = chargeText;
|
this.chargeText = chargeText;
|
||||||
this.tagType = tagType!; // TODO: is this bang correct?
|
this.tagType = tagType!; // TODO: is this bang correct?
|
||||||
this.chargeEffect = chargeEffect;
|
this.chargeEffect = chargeEffect;
|
||||||
this.sameTurn = sameTurn;
|
|
||||||
this.followUpPriority = followUpPriority!; // TODO: is this bang correct?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const lastMove = user.getLastXMoves().find(() => true);
|
const lastMove = user.getLastXMoves().find(() => true);
|
||||||
if (!lastMove || lastMove.move !== move.id || (lastMove.result !== MoveResult.OTHER && (this.sameTurn || lastMove.turn !== user.scene.currentBattle.turn))) {
|
if (!lastMove || lastMove.move !== move.id || (lastMove.result !== MoveResult.OTHER && lastMove.turn !== user.scene.currentBattle.turn)) {
|
||||||
(args[0] as Utils.BooleanHolder).value = true;
|
(args[0] as Utils.BooleanHolder).value = true;
|
||||||
new MoveChargeAnim(this.chargeAnim, move.id, user).play(user.scene, () => {
|
new MoveChargeAnim(this.chargeAnim, move.id, user).play(user.scene, () => {
|
||||||
user.scene.queueMessage(this.chargeText.replace("{TARGET}", getPokemonNameWithAffix(target)).replace("{USER}", getPokemonNameWithAffix(user)));
|
user.scene.queueMessage(this.chargeText.replace("{TARGET}", getPokemonNameWithAffix(target)).replace("{USER}", getPokemonNameWithAffix(user)));
|
||||||
@ -2420,13 +2433,6 @@ export class ChargeAttr extends OverrideMoveEffectAttr {
|
|||||||
}
|
}
|
||||||
user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER });
|
user.pushMoveHistory({ move: move.id, targets: [ target.getBattlerIndex() ], result: MoveResult.OTHER });
|
||||||
user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true });
|
user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true });
|
||||||
if (this.sameTurn) {
|
|
||||||
let movesetMove = user.moveset.find(m => m?.moveId === move.id);
|
|
||||||
if (!movesetMove) { // account for any move that calls a ChargeAttr move when the ChargeAttr move does not exist in moveset
|
|
||||||
movesetMove = new PokemonMove(move.id, 0, 0, true);
|
|
||||||
}
|
|
||||||
user.scene.pushMovePhase(new MovePhase(user.scene, user, [ target.getBattlerIndex() ], movesetMove, true), this.followUpPriority!); // TODO: is this bang correct?
|
|
||||||
}
|
|
||||||
user.addTag(BattlerTagType.CHARGING, 1, move.id, user.id);
|
user.addTag(BattlerTagType.CHARGING, 1, move.id, user.id);
|
||||||
resolve(true);
|
resolve(true);
|
||||||
});
|
});
|
||||||
@ -8081,11 +8087,10 @@ export function initMoves() {
|
|||||||
.attr(StatChangeAttr, BattleStat.ATK, -1),
|
.attr(StatChangeAttr, BattleStat.ATK, -1),
|
||||||
new StatusMove(Moves.INSTRUCT, Type.PSYCHIC, -1, 15, -1, 0, 7)
|
new StatusMove(Moves.INSTRUCT, Type.PSYCHIC, -1, 15, -1, 0, 7)
|
||||||
.unimplemented(),
|
.unimplemented(),
|
||||||
new AttackMove(Moves.BEAK_BLAST, Type.FLYING, MoveCategory.PHYSICAL, 100, 100, 15, -1, 5, 7)
|
new AttackMove(Moves.BEAK_BLAST, Type.FLYING, MoveCategory.PHYSICAL, 100, 100, 15, -1, -3, 7)
|
||||||
.attr(ChargeAttr, ChargeAnim.BEAK_BLAST_CHARGING, i18next.t("moveTriggers:startedHeatingUpBeak", {pokemonName: "{USER}"}), undefined, false, true, -3)
|
.attr(BeakBlastHeaderAttr)
|
||||||
.ballBombMove()
|
.ballBombMove()
|
||||||
.makesContact(false)
|
.makesContact(false),
|
||||||
.partial(),
|
|
||||||
new AttackMove(Moves.CLANGING_SCALES, Type.DRAGON, MoveCategory.SPECIAL, 110, 100, 5, -1, 0, 7)
|
new AttackMove(Moves.CLANGING_SCALES, Type.DRAGON, MoveCategory.SPECIAL, 110, 100, 5, -1, 0, 7)
|
||||||
.attr(StatChangeAttr, BattleStat.DEF, -1, true, null, true, false, MoveEffectTrigger.HIT, true)
|
.attr(StatChangeAttr, BattleStat.DEF, -1, true, null, true, false, MoveEffectTrigger.HIT, true)
|
||||||
.soundBased()
|
.soundBased()
|
||||||
|
@ -66,5 +66,6 @@ export enum BattlerTagType {
|
|||||||
IGNORE_GHOST = "IGNORE_GHOST",
|
IGNORE_GHOST = "IGNORE_GHOST",
|
||||||
IGNORE_DARK = "IGNORE_DARK",
|
IGNORE_DARK = "IGNORE_DARK",
|
||||||
GULP_MISSILE_ARROKUDA = "GULP_MISSILE_ARROKUDA",
|
GULP_MISSILE_ARROKUDA = "GULP_MISSILE_ARROKUDA",
|
||||||
GULP_MISSILE_PIKACHU = "GULP_MISSILE_PIKACHU"
|
GULP_MISSILE_PIKACHU = "GULP_MISSILE_PIKACHU",
|
||||||
|
BEAK_BLAST_CHARGING = "BEAK_BLAST_CHARGING"
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||||
|
|
||||||
export const abilityTriggers: SimpleTranslationEntries = {
|
export const abilityTriggers: SimpleTranslationEntries = {
|
||||||
"blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}} vor Rückstoß geschützt!",
|
"blockRecoilDamage": "{{pokemonName}} wurde durch {{abilityName}} vor Rückstoß geschützt!",
|
||||||
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
|
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
|
||||||
"costar": "{{pokemonName}} kopiert die Statusveränderungen von {{allyName}}!",
|
"costar": "{{pokemonName}} kopiert die Statusveränderungen von {{allyName}}!",
|
||||||
"iceFaceAvoidedDamage": "{{pokemonName}} wehrt Schaden mit {{abilityName}} ab!",
|
"iceFaceAvoidedDamage": "{{pokemonName}} wehrt Schaden mit {{abilityName}} ab!",
|
||||||
|
@ -5,4 +5,5 @@ export const pokemonInfoContainer: SimpleTranslationEntries = {
|
|||||||
"gender": "Geschlecht:",
|
"gender": "Geschlecht:",
|
||||||
"ability": "Fähigkeit:",
|
"ability": "Fähigkeit:",
|
||||||
"nature": "Wesen:",
|
"nature": "Wesen:",
|
||||||
|
"form": "Form:",
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -3,6 +3,7 @@ import { PokemonInfoTranslationEntries } from "#app/interfaces/locales";
|
|||||||
export const pokemonInfo: PokemonInfoTranslationEntries = {
|
export const pokemonInfo: PokemonInfoTranslationEntries = {
|
||||||
Stat: {
|
Stat: {
|
||||||
"HP": "KP",
|
"HP": "KP",
|
||||||
|
"HPStat": "KP",
|
||||||
"HPshortened": "KP",
|
"HPshortened": "KP",
|
||||||
"ATK": "Angriff",
|
"ATK": "Angriff",
|
||||||
"ATKshortened": "Ang",
|
"ATKshortened": "Ang",
|
||||||
|
@ -1,62 +1,63 @@
|
|||||||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||||
|
|
||||||
export const abilityTriggers: SimpleTranslationEntries = {
|
export const abilityTriggers: SimpleTranslationEntries = {
|
||||||
"blockRecoilDamage" : "{{pokemonName}}は {{abilityName}}で\nはんどうダメージを うけない!",
|
"blockRecoilDamage" : "{{pokemonName}}は {{abilityName}}で 反動ダメージを 受けない!",
|
||||||
"badDreams": "{{pokemonName}}は ナイトメアに うなされている!",
|
"badDreams": "{{pokemonName}}は ナイトメアに うなされている!",
|
||||||
"costar": "{{pokemonName}} copied {{allyName}}'s stat changes!",
|
"costar": "{{pokemonName}}は {{allyName}}の\n能力変化を コピーした!",
|
||||||
"iceFaceAvoidedDamage": "{{pokemonName}}は\n{{abilityName}}で ダメージを うけない!",
|
"iceFaceAvoidedDamage": "{{pokemonName}}は\n{{abilityName}}で ダメージを 受けない!",
|
||||||
"perishBody": "{{pokemonName}}の {{abilityName}}で\nおたがいは 3ターンごに ほろびてしまう!",
|
"perishBody": "{{pokemonName}}の {{abilityName}}で\nおたがいは 3ターン後に ほろびいてしまう!",
|
||||||
"poisonHeal": "{{pokemonName}}は {{abilityName}}で\nかいふくした!",
|
"poisonHeal": "{{pokemonName}}は {{abilityName}}で 回復した!",
|
||||||
"trace": "{{pokemonName}} copied {{targetName}}'s\n{{abilityName}}!",
|
"trace": "{{pokemonName}}は 相手の {{targetName}}の\n{{abilityName}}を トレースした!",
|
||||||
"windPowerCharged": "{{pokemonName}}は\n{{moveName}}を うけて じゅうでんした!",
|
"windPowerCharged": "{{pokemonName}}は\n{{moveName}}を 受けて じゅうでんした!",
|
||||||
"quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
|
"quickDraw": "{{pokemonName}}は クイックドロウで\n行動が はやくなった!",
|
||||||
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
|
"blockItemTheft": "{{pokemonNameWithAffix}}の {{abilityName}}で\n道具を うばわれない!",
|
||||||
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
"typeImmunityHeal": "{{pokemonNameWithAffix}}は {{abilityName}}で\n体力を 回復した!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}}は {{abilityName}}で\nダメージを 受けない。",
|
||||||
"postDefendDisguise": "{{pokemonNameWithAffix}}'s disguise was busted!",
|
"postDefendDisguise": "{{pokemonNameWithAffix}}の\nばけのかわが はがれた!",
|
||||||
"moveImmunity": "It doesn't affect {{pokemonNameWithAffix}}!",
|
"moveImmunity": "{{pokemonNameWithAffix}}には\n効果が ないようだ…",
|
||||||
"reverseDrain": "{{pokemonNameWithAffix}} sucked up the liquid ooze!",
|
"reverseDrain": "{{pokemonNameWithAffix}}は\nヘドロえきを 吸い取った!",
|
||||||
"postDefendTypeChange": "{{pokemonNameWithAffix}}'s {{abilityName}}\nmade it the {{typeName}} type!",
|
"postDefendTypeChange": "{{pokemonNameWithAffix}}は {{abilityName}}で\n{{typeName}}タイプに なった!",
|
||||||
"postDefendContactDamage": "{{pokemonNameWithAffix}}'s {{abilityName}}\nhurt its attacker!",
|
"postDefendContactDamage": "{{pokemonNameWithAffix}}は {{abilityName}}で\n相手を キズつけた!",
|
||||||
"postDefendAbilitySwap": "{{pokemonNameWithAffix}} swapped\nabilities with its target!",
|
"postDefendAbilitySwap": "{{pokemonNameWithAffix}}は\nおたがいの 特性を 入れ替えた!",
|
||||||
"postDefendAbilityGive": "{{pokemonNameWithAffix}} gave its target\n{{abilityName}}!",
|
"postDefendAbilityGive": "{{pokemonNameWithAffix}}は\n特性が {{abilityName}}に なっちゃった!",
|
||||||
"postDefendMoveDisable": "{{pokemonNameWithAffix}}'s {{moveName}}\nwas disabled!",
|
"postDefendMoveDisable": "{{pokemonNameWithAffix}}の\n{{moveName}}を 封じこめた!",
|
||||||
"pokemonTypeChange": "{{pokemonNameWithAffix}} transformed into the {{moveType}} type!",
|
"pokemonTypeChange": "{{pokemonNameWithAffix}}は\n{{moveType}}タイプに なった!",
|
||||||
"postAttackStealHeldItem": "{{pokemonNameWithAffix}} stole\n{{defenderName}}'s {{stolenItemType}}!",
|
"postAttackStealHeldItem": "{{pokemonNameWithAffix}}は {{defenderName}}から\n{{stolenItemType}}を うばいとった!",
|
||||||
"postDefendStealHeldItem": "{{pokemonNameWithAffix}} stole\n{{attackerName}}'s {{stolenItemType}}!",
|
"postDefendStealHeldItem": "{{pokemonNameWithAffix}}は {{attackerName}}から\n{{stolenItemType}}を うばいとった!",
|
||||||
"copyFaintedAllyAbility": "{{pokemonNameWithAffix}}'s {{abilityName}} was taken over!",
|
"copyFaintedAllyAbility": "{{pokemonNameWithAffix}}の\n{{abilityName}}を 引き継いだ!",
|
||||||
"intimidateImmunity": "{{pokemonNameWithAffix}}'s {{abilityName}} prevented it from being Intimidated!",
|
"intimidateImmunity": "{{pokemonNameWithAffix}}は\n{{abilityName}}の 効果で 能力が 下がらない!",
|
||||||
"postSummonAllyHeal": "{{pokemonNameWithAffix}} drank down all the\nmatcha that {{pokemonName}} made!",
|
"postSummonAllyHeal": "{{pokemonNameWithAffix}}が たてた お茶を\n{{pokemonName}}は 飲みほした!",
|
||||||
"postSummonClearAllyStats": "{{pokemonNameWithAffix}}'s stat changes\nwere removed!",
|
"postSummonClearAllyStats": "{{pokemonNameWithAffix}}の\n能力変化が 元に戻った!",
|
||||||
"postSummonTransform": "{{pokemonNameWithAffix}} transformed\ninto {{targetName}}!",
|
"postSummonTransform": "{{pokemonNameWithAffix}}は\n{{targetName}}に 変身した!",
|
||||||
"protectStat": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents lowering its {{statName}}!",
|
"protectStat": "{{pokemonNameWithAffix}}は {{abilityName}}の 効果で\n{{statName}}が 下がらない!",
|
||||||
"statusEffectImmunityWithName": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents {{statusEffectName}}!",
|
"statusEffectImmunityWithName": "{{pokemonNameWithAffix}}は {{abilityName}}で\{{statusEffectName}}に ならない!",
|
||||||
"statusEffectImmunity": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents status problems!",
|
"statusEffectImmunity": "{{pokemonNameWithAffix}}は {{abilityName}}で\n状態異常に ならない!",
|
||||||
"battlerTagImmunity": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents {{battlerTagName}}!",
|
"battlerTagImmunity": "{{pokemonNameWithAffix}}は {{abilityName}}で]\n{{battlerTagName}}を 無視した!",
|
||||||
"forewarn": "{{pokemonNameWithAffix}} was forewarned about {{moveName}}!",
|
"forewarn": "{{pokemonNameWithAffix}}の\n{{moveName}}を 読み取った!",
|
||||||
"frisk": "{{pokemonNameWithAffix}} frisked {{opponentName}}'s {{opponentAbilityName}}!",
|
"frisk": "{{pokemonNameWithAffix}}は {{opponentName}}の\n{{opponentAbilityName}}を お見通しだ!",
|
||||||
"postWeatherLapseHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
"postWeatherLapseHeal": "{{pokemonNameWithAffix}}は {{abilityName}}で\n体力を 回復した!",
|
||||||
"postWeatherLapseDamage": "{{pokemonNameWithAffix}} is hurt\nby its {{abilityName}}!",
|
"postWeatherLapseDamage": "{{pokemonNameWithAffix}}は\n{{abilityName}}の ダメージを 受けた!",
|
||||||
"postTurnLootCreateEatenBerry": "{{pokemonNameWithAffix}} harvested one {{berryName}}!",
|
"postTurnLootCreateEatenBerry": "{{pokemonNameWithAffix}}は\n{{berryName}}を 収穫した!",
|
||||||
"postTurnHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
"postTurnHeal": "{{pokemonNameWithAffix}}は {{abilityName}}で\n体力を 回復した!",
|
||||||
"fetchBall": "{{pokemonNameWithAffix}} found a\n{{pokeballName}}!",
|
"fetchBall": "{{pokemonNameWithAffix}}は\n{{pokeballName}}を 拾ってきた!",
|
||||||
"healFromBerryUse": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP!",
|
"healFromBerryUse": "{{pokemonNameWithAffix}}は {{abilityName}}で\n体力を 回復した!",
|
||||||
"arenaTrap": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents switching!",
|
"arenaTrap": "{{pokemonNameWithAffix}}の {{abilityName}}で\n入れ替えることが できない!",
|
||||||
"postBattleLoot": "{{pokemonNameWithAffix}} picked up\n{{itemName}}!",
|
"postBattleLoot": "{{pokemonNameWithAffix}}は\n{{itemName}}を 拾った!",
|
||||||
"postFaintContactDamage": "{{pokemonNameWithAffix}}'s {{abilityName}}\nhurt its attacker!",
|
"postFaintContactDamage": "{{pokemonNameWithAffix}}は {{abilityName}}で\n相手に ダメージを 与えた!",
|
||||||
"postFaintHpDamage": "{{pokemonNameWithAffix}}'s {{abilityName}}\nhurt its attacker!",
|
"postFaintHpDamage": "{{pokemonNameWithAffix}}は {{abilityName}}で\n相手に ダメージを 与えた!",
|
||||||
"postSummonPressure": "{{pokemonNameWithAffix}} is exerting its Pressure!",
|
"postSummonPressure": "{{pokemonNameWithAffix}}は\nプレッシャーを 放っている!",
|
||||||
"postSummonMoldBreaker": "{{pokemonNameWithAffix}} breaks the mold!",
|
"postSummonMoldBreaker": "{{pokemonNameWithAffix}}は\nかたやぶりだ!",
|
||||||
"postSummonAnticipation": "{{pokemonNameWithAffix}} shuddered!",
|
"postSummonAnticipation": "{{pokemonNameWithAffix}}は\nみぶるいした!",
|
||||||
"postSummonTurboblaze": "{{pokemonNameWithAffix}} is radiating a blazing aura!",
|
"postSummonTurboblaze": "{{pokemonNameWithAffix}}は\n燃え盛(もえさか)る オーラを 放っている!",
|
||||||
"postSummonTeravolt": "{{pokemonNameWithAffix}} is radiating a bursting aura!",
|
"postSummonTeravolt": "{{pokemonNameWithAffix}}は\n弾(はじ)ける オーラを 放っている!",
|
||||||
"postSummonDarkAura": "{{pokemonNameWithAffix}} is radiating a Dark Aura!",
|
"postSummonDarkAura": "{{pokemonNameWithAffix}}は\nダークオーラを 放っている!",
|
||||||
"postSummonFairyAura": "{{pokemonNameWithAffix}} is radiating a Fairy Aura!",
|
"postSummonFairyAura": "{{pokemonNameWithAffix}}は\nフェアリーオーラを 放っている!",
|
||||||
"postSummonNeutralizingGas": "{{pokemonNameWithAffix}}'s Neutralizing Gas filled the area!",
|
"postSummonNeutralizingGas": "あたりに かがくへんかガスが 充満した!",
|
||||||
"postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} has two Abilities!",
|
"postSummonAsOneGlastrier": "{{pokemonNameWithAffix}}は\nふたつの 特性を あわせ持つ!",
|
||||||
"postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} has two Abilities!",
|
"postSummonAsOneSpectrier": "{{pokemonNameWithAffix}}は\nふたつの 特性を あわせ持つ!",
|
||||||
"postSummonVesselOfRuin": "{{pokemonNameWithAffix}}'s Vessel of Ruin lowered the {{statName}}\nof all surrounding Pokémon!",
|
"postSummonVesselOfRuin": "{{pokemonNameWithAffix}}の わざわいのうつわで\nまわりの {{statName}}が 弱まった!",
|
||||||
"postSummonSwordOfRuin": "{{pokemonNameWithAffix}}'s Sword of Ruin lowered the {{statName}}\nof all surrounding Pokémon!",
|
"postSummonSwordOfRuin": "{{pokemonNameWithAffix}}の わざわいのつるぎで\nまわりの {{statName}}が 弱まった!",
|
||||||
"postSummonTabletsOfRuin": "{{pokemonNameWithAffix}}'s Tablets of Ruin lowered the {{statName}}\nof all surrounding Pokémon!",
|
"postSummonTabletsOfRuin": "{{pokemonNameWithAffix}}の わざわいのおふだ\nまわりの {{statName}}が 弱まった!",
|
||||||
"postSummonBeadsOfRuin": "{{pokemonNameWithAffix}}'s Beads of Ruin lowered the {{statName}}\nof all surrounding Pokémon!",
|
"postSummonBeadsOfRuin": "{{pokemonNameWithAffix}}の わざわいのたまで\nまわりの {{statName}}が 弱まった!",
|
||||||
|
"preventBerryUse": "{{pokemonNameWithAffix}}は 緊張して\nきのみが 食べられなくなった!",
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -2,7 +2,7 @@ import { StatusEffectTranslationEntries } from "#app/interfaces/locales.js";
|
|||||||
|
|
||||||
export const statusEffect: StatusEffectTranslationEntries = {
|
export const statusEffect: StatusEffectTranslationEntries = {
|
||||||
none: {
|
none: {
|
||||||
name: "None",
|
name: "なし",
|
||||||
description: "",
|
description: "",
|
||||||
obtain: "",
|
obtain: "",
|
||||||
obtainSource: "",
|
obtainSource: "",
|
||||||
@ -11,57 +11,57 @@ export const statusEffect: StatusEffectTranslationEntries = {
|
|||||||
heal: ""
|
heal: ""
|
||||||
},
|
},
|
||||||
poison: {
|
poison: {
|
||||||
name: "Poison",
|
name: "どく",
|
||||||
description: "poisoning",
|
description: "どく",
|
||||||
obtain: "{{pokemonNameWithAffix}}\nwas poisoned!",
|
obtain: "{{pokemonNameWithAffix}}は\n毒を あびた!",
|
||||||
obtainSource: "{{pokemonNameWithAffix}}\nwas poisoned by the {{sourceText}}!",
|
obtainSource: "{{pokemonNameWithAffix}}は\n{{sourceText}}で 毒を あびた!",
|
||||||
activation: "{{pokemonNameWithAffix}} is hurt\nby poison!",
|
activation: "{{pokemonNameWithAffix}}は\n毒の ダメージを 受けた!",
|
||||||
overlap: "{{pokemonNameWithAffix}} is\nalready poisoned!",
|
overlap: "{{pokemonNameWithAffix}}は すでに\n毒を あびている",
|
||||||
heal: "{{pokemonNameWithAffix}} was\ncured of its poison!"
|
heal: "{{pokemonNameWithAffix}}の 毒は\nきれいさっぱり なくなった!"
|
||||||
},
|
},
|
||||||
toxic: {
|
toxic: {
|
||||||
name: "Toxic",
|
name: "もうどく",
|
||||||
description: "poisoning",
|
description: "もうどく",
|
||||||
obtain: "{{pokemonNameWithAffix}}\nwas badly poisoned!",
|
obtain: "{{pokemonNameWithAffix}}は\n猛毒を あびた!",
|
||||||
obtainSource: "{{pokemonNameWithAffix}}\nwas badly poisoned by the {{sourceText}}!",
|
obtainSource: "{{pokemonNameWithAffix}}は\n{{sourceText}}で 猛毒を あびた!",
|
||||||
activation: "{{pokemonNameWithAffix}} is hurt\nby poison!",
|
activation: "{{pokemonNameWithAffix}}は\n毒の ダメージを受けた!",
|
||||||
overlap: "{{pokemonNameWithAffix}} is\nalready poisoned!",
|
overlap: "{{pokemonNameWithAffix}}は すでに\n毒を あびている",
|
||||||
heal: "{{pokemonNameWithAffix}} was\ncured of its poison!"
|
heal: "{{pokemonNameWithAffix}}の 毒は\nきれいさっぱり なくなった!"
|
||||||
},
|
},
|
||||||
paralysis: {
|
paralysis: {
|
||||||
name: "Paralysis",
|
name: "まひ",
|
||||||
description: "paralysis",
|
description: "まひ",
|
||||||
obtain: "{{pokemonNameWithAffix}} was paralyzed,\nIt may be unable to move!",
|
obtain: "{{pokemonNameWithAffix}}は まひして\n技が でにくくなった!",
|
||||||
obtainSource: "{{pokemonNameWithAffix}} was paralyzed by the {{sourceText}}!\nIt may be unable to move!",
|
obtainSource: "{{pokemonNameWithAffix}}は {{sourceText}}で まひして\n技が でにくくなった!",
|
||||||
activation: "{{pokemonNameWithAffix}} is paralyzed!\nIt can't move!",
|
activation: "{{pokemonNameWithAffix}}は\n体が しびれて 動けない!",
|
||||||
overlap: "{{pokemonNameWithAffix}} is\nalready paralyzed!",
|
overlap: "{{pokemonNameWithAffix}}は\nすでに まひしている",
|
||||||
heal: "{{pokemonNameWithAffix}} was\nhealed of paralysis!"
|
heal: "{{pokemonNameWithAffix}}の\nしびれが とれた!"
|
||||||
},
|
},
|
||||||
sleep: {
|
sleep: {
|
||||||
name: "Sleep",
|
name: "ねむり",
|
||||||
description: "sleep",
|
description: "ねむり",
|
||||||
obtain: "{{pokemonNameWithAffix}}\nfell asleep!",
|
obtain: "{{pokemonNameWithAffix}}は\n眠ってしまった!",
|
||||||
obtainSource: "{{pokemonNameWithAffix}}\nfell asleep from the {{sourceText}}!",
|
obtainSource: "{{pokemonNameWithAffix}}は\n{{sourceText}}で 眠ってしまった!",
|
||||||
activation: "{{pokemonNameWithAffix}} is fast asleep.",
|
activation: "{{pokemonNameWithAffix}}は\nぐうぐう 眠っている",
|
||||||
overlap: "{{pokemonNameWithAffix}} is\nalready asleep!",
|
overlap: "{{pokemonNameWithAffix}}は\nすでに 眠っている",
|
||||||
heal: "{{pokemonNameWithAffix}} woke up!"
|
heal: "{{pokemonNameWithAffix}}は\n目を 覚ました!"
|
||||||
},
|
},
|
||||||
freeze: {
|
freeze: {
|
||||||
name: "Freeze",
|
name: "こおり",
|
||||||
description: "freezing",
|
description: "こおり",
|
||||||
obtain: "{{pokemonNameWithAffix}}\nwas frozen solid!",
|
obtain: "{{pokemonNameWithAffix}}は\n凍りついた!",
|
||||||
obtainSource: "{{pokemonNameWithAffix}}\nwas frozen solid by the {{sourceText}}!",
|
obtainSource: "{{pokemonNameWithAffix}}は\n{{sourceText}}で 凍りついた!",
|
||||||
activation: "{{pokemonNameWithAffix}} is\nfrozen solid!",
|
activation: "{{pokemonNameWithAffix}}は\n凍ってしまって 動けない!",
|
||||||
overlap: "{{pokemonNameWithAffix}} is\nalready frozen!",
|
overlap: "{{pokemonNameWithAffix}}は\nすでに 凍っている",
|
||||||
heal: "{{pokemonNameWithAffix}} was\ndefrosted!"
|
heal: "{{pokemonNameWithAffix}}は\nこおり状態が 治った!"
|
||||||
},
|
},
|
||||||
burn: {
|
burn: {
|
||||||
name: "Burn",
|
name: "やけど",
|
||||||
description: "burn",
|
description: "やけど",
|
||||||
obtain: "{{pokemonNameWithAffix}}\nwas burned!",
|
obtain: "{{pokemonNameWithAffix}}は\nやけどを 負った!",
|
||||||
obtainSource: "{{pokemonNameWithAffix}}\nwas burned by the {{sourceText}}!",
|
obtainSource: "{{pokemonNameWithAffix}}は\n{{sourceText}}で やけどを 負った!",
|
||||||
activation: "{{pokemonNameWithAffix}} is hurt\nby its burn!",
|
activation: "{{pokemonNameWithAffix}}は\nやけどの ダメージを 受けた!",
|
||||||
overlap: "{{pokemonNameWithAffix}} is\nalready burned!",
|
overlap: "{{pokemonNameWithAffix}}は すでに\nやけどを 負っている",
|
||||||
heal: "{{pokemonNameWithAffix}} was\nhealed of its burn!"
|
heal: "{{pokemonNameWithAffix}}の\nやけどが 治った!"
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -3087,6 +3087,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||||||
Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT
|
Utils.executeIf(!isProtected && !chargeEffect, () => applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.HIT
|
||||||
&& (!attr.firstHitOnly || firstHit) && (!attr.lastHitOnly || lastHit) && (!attr.firstTargetOnly || firstTarget), user, target, this.move.getMove()).then(() => {
|
&& (!attr.firstHitOnly || firstHit) && (!attr.lastHitOnly || lastHit) && (!attr.firstTargetOnly || firstTarget), user, target, this.move.getMove()).then(() => {
|
||||||
return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move.getMove(), hitResult).then(() => {
|
return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move.getMove(), hitResult).then(() => {
|
||||||
|
target.lapseTag(BattlerTagType.BEAK_BLAST_CHARGING);
|
||||||
if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) {
|
if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) {
|
||||||
user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target);
|
user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import i18next from "i18next";
|
|||||||
import LanguageDetector from "i18next-browser-languagedetector";
|
import LanguageDetector from "i18next-browser-languagedetector";
|
||||||
import processor, { KoreanPostpositionProcessor } from "i18next-korean-postposition-processor";
|
import processor, { KoreanPostpositionProcessor } from "i18next-korean-postposition-processor";
|
||||||
|
|
||||||
import { caESConfig} from "#app/locales/ca-ES/config.js";
|
import { caESConfig} from "#app/locales/ca_ES/config.js";
|
||||||
import { deConfig } from "#app/locales/de/config.js";
|
import { deConfig } from "#app/locales/de/config.js";
|
||||||
import { enConfig } from "#app/locales/en/config.js";
|
import { enConfig } from "#app/locales/en/config.js";
|
||||||
import { esConfig } from "#app/locales/es/config.js";
|
import { esConfig } from "#app/locales/es/config.js";
|
||||||
|
@ -197,6 +197,7 @@ export interface StarterAttributes {
|
|||||||
variant?: integer;
|
variant?: integer;
|
||||||
form?: integer;
|
form?: integer;
|
||||||
female?: boolean;
|
female?: boolean;
|
||||||
|
shiny?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StarterPreferences {
|
export interface StarterPreferences {
|
||||||
|
135
src/test/moves/beak_blast.test.ts
Normal file
135
src/test/moves/beak_blast.test.ts
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
import GameManager from "#test/utils/gameManager";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||||
|
import { BerryPhase, MovePhase, TurnEndPhase } from "#app/phases";
|
||||||
|
import { BattlerTagType } from "#app/enums/battler-tag-type.js";
|
||||||
|
import { StatusEffect } from "#app/enums/status-effect.js";
|
||||||
|
|
||||||
|
const TIMEOUT = 20 * 1000;
|
||||||
|
|
||||||
|
describe("Moves - Beak Blast", () => {
|
||||||
|
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
|
||||||
|
.battleType("single")
|
||||||
|
.ability(Abilities.UNNERVE)
|
||||||
|
.moveset([Moves.BEAK_BLAST])
|
||||||
|
.enemySpecies(Species.SNORLAX)
|
||||||
|
.enemyAbility(Abilities.INSOMNIA)
|
||||||
|
.enemyMoveset(Array(4).fill(Moves.TACKLE))
|
||||||
|
.startingLevel(100)
|
||||||
|
.enemyLevel(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should add a charge effect that burns attackers on contact",
|
||||||
|
async () => {
|
||||||
|
await game.startBattle([Species.BLASTOISE]);
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST));
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(MovePhase, false);
|
||||||
|
expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.status?.effect).toBe(StatusEffect.BURN);
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should still charge and burn opponents if the user is sleeping",
|
||||||
|
async () => {
|
||||||
|
game.override.statusEffect(StatusEffect.SLEEP);
|
||||||
|
|
||||||
|
await game.startBattle([Species.BLASTOISE]);
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST));
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(MovePhase, false);
|
||||||
|
expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.status?.effect).toBe(StatusEffect.BURN);
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should not burn attackers that don't make contact",
|
||||||
|
async () => {
|
||||||
|
game.override.enemyMoveset(Array(4).fill(Moves.WATER_GUN));
|
||||||
|
|
||||||
|
await game.startBattle([Species.BLASTOISE]);
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST));
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(MovePhase, false);
|
||||||
|
expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(enemyPokemon.status?.effect).not.toBe(StatusEffect.BURN);
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should only hit twice with Multi-Lens",
|
||||||
|
async () => {
|
||||||
|
game.override.startingHeldItems([{name: "MULTI_LENS", count: 1}]);
|
||||||
|
|
||||||
|
await game.startBattle([Species.BLASTOISE]);
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST));
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(BerryPhase, false);
|
||||||
|
expect(leadPokemon.turnData.hitCount).toBe(2);
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"should be blocked by Protect",
|
||||||
|
async () => {
|
||||||
|
game.override.enemyMoveset(Array(4).fill(Moves.PROTECT));
|
||||||
|
|
||||||
|
await game.startBattle([Species.BLASTOISE]);
|
||||||
|
|
||||||
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.BEAK_BLAST));
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(MovePhase, false);
|
||||||
|
expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeDefined();
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp());
|
||||||
|
expect(leadPokemon.getTag(BattlerTagType.BEAK_BLAST_CHARGING)).toBeUndefined();
|
||||||
|
}, TIMEOUT
|
||||||
|
);
|
||||||
|
});
|
@ -2,10 +2,11 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import GameManager from "#test/utils/gameManager";
|
import GameManager from "#test/utils/gameManager";
|
||||||
import { Species } from "#app/enums/species.js";
|
import { Species } from "#app/enums/species.js";
|
||||||
import { SPLASH_ONLY } from "../utils/testUtils";
|
import { mockTurnOrder, SPLASH_ONLY } from "../utils/testUtils";
|
||||||
import { Moves } from "#app/enums/moves.js";
|
import { Moves } from "#app/enums/moves.js";
|
||||||
import { getMovePosition } from "../utils/gameManagerUtils";
|
import { getMovePosition } from "../utils/gameManagerUtils";
|
||||||
import { MoveEffectPhase } from "#app/phases.js";
|
import { MoveEffectPhase } from "#app/phases.js";
|
||||||
|
import { BattlerIndex } from "#app/battle.js";
|
||||||
|
|
||||||
describe("Internals", () => {
|
describe("Internals", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -38,6 +39,7 @@ describe("Internals", () => {
|
|||||||
const enemy = game.scene.getEnemyPokemon()!;
|
const enemy = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
game.doAttack(getMovePosition(game.scene, 0, Moves.CONFUSION));
|
game.doAttack(getMovePosition(game.scene, 0, Moves.CONFUSION));
|
||||||
|
await mockTurnOrder(game, [BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
|
||||||
await game.toNextTurn();
|
await game.toNextTurn();
|
||||||
expect(enemy.hp).toBe(enemy.getMaxHp());
|
expect(enemy.hp).toBe(enemy.getMaxHp());
|
||||||
|
|
||||||
|
@ -51,6 +51,9 @@ describe("UI - Starter select", () => {
|
|||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
@ -112,6 +115,9 @@ describe("UI - Starter select", () => {
|
|||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.CYCLE_GENDER);
|
handler.processInput(Button.CYCLE_GENDER);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
@ -176,6 +182,9 @@ describe("UI - Starter select", () => {
|
|||||||
handler.processInput(Button.CYCLE_GENDER);
|
handler.processInput(Button.CYCLE_GENDER);
|
||||||
handler.processInput(Button.CYCLE_NATURE);
|
handler.processInput(Button.CYCLE_NATURE);
|
||||||
handler.processInput(Button.CYCLE_ABILITY);
|
handler.processInput(Button.CYCLE_ABILITY);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
@ -238,6 +247,9 @@ describe("UI - Starter select", () => {
|
|||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.CYCLE_GENDER);
|
handler.processInput(Button.CYCLE_GENDER);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
@ -298,7 +310,6 @@ describe("UI - Starter select", () => {
|
|||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.CYCLE_SHINY);
|
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
@ -358,7 +369,7 @@ describe("UI - Starter select", () => {
|
|||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
@ -419,7 +430,7 @@ describe("UI - Starter select", () => {
|
|||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
|
@ -1303,11 +1303,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
const isPartyValid = this.isPartyValid();
|
const isPartyValid = this.isPartyValid();
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
if (isPartyValid) {
|
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true)), this.starterSpecies.length !== 0);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)), isPartyValid);
|
||||||
} else {
|
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true)), this.starterSpecies.length !== 0, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentPartyValue = this.starterSpecies.map(s => s.generation).reduce((total: number, gen: number, i: number) => total += this.scene.gameData.getSpeciesStarterValue(this.starterSpecies[i].speciesId), 0);
|
const currentPartyValue = this.starterSpecies.map(s => s.generation).reduce((total: number, gen: number, i: number) => total += this.scene.gameData.getSpeciesStarterValue(this.starterSpecies[i].speciesId), 0);
|
||||||
const newCost = this.scene.gameData.getSpeciesStarterValue(species.speciesId);
|
const newCost = this.scene.gameData.getSpeciesStarterValue(species.speciesId);
|
||||||
@ -1661,7 +1658,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor);
|
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId));
|
||||||
// prepare persistent starter data to store changes
|
// prepare persistent starter data to store changes
|
||||||
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
|
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
|
||||||
if (!starterAttributes) {
|
if (!starterAttributes) {
|
||||||
@ -1671,8 +1668,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
case Button.CYCLE_SHINY:
|
case Button.CYCLE_SHINY:
|
||||||
if (this.canCycleShiny) {
|
if (this.canCycleShiny) {
|
||||||
const newVariant = props.variant;
|
const newVariant = props.variant;
|
||||||
|
starterAttributes.shiny = starterAttributes.shiny ? !starterAttributes.shiny : true;
|
||||||
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined);
|
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined);
|
||||||
if (this.dexAttrCursor & DexAttr.SHINY) {
|
if (starterAttributes.shiny) {
|
||||||
this.scene.playSound("sparkle");
|
this.scene.playSound("sparkle");
|
||||||
// Set the variant label to the shiny tint
|
// Set the variant label to the shiny tint
|
||||||
const tint = getVariantTint(newVariant);
|
const tint = getVariantTint(newVariant);
|
||||||
@ -1680,6 +1678,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonShinyIcon.setTint(tint);
|
this.pokemonShinyIcon.setTint(tint);
|
||||||
this.pokemonShinyIcon.setVisible(true);
|
this.pokemonShinyIcon.setVisible(true);
|
||||||
} else {
|
} else {
|
||||||
|
// starterAttributes.variant = 0;
|
||||||
|
if (starterAttributes?.variant) {
|
||||||
|
delete starterAttributes.variant;
|
||||||
|
}
|
||||||
this.pokemonShinyIcon.setVisible(false);
|
this.pokemonShinyIcon.setVisible(false);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
@ -1948,6 +1950,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.updateInstructions();
|
this.updateInstructions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePartyIcon(species: PokemonSpecies, index: number) {
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId));
|
||||||
|
this.starterIcons[index].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
|
||||||
|
this.starterIcons[index].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
||||||
|
this.checkIconId(this.starterIcons[index], species, props.female, props.formIndex, props.shiny, props.variant);
|
||||||
|
}
|
||||||
|
|
||||||
switchMoveHandler(i: number, newMove: Moves, move: Moves) {
|
switchMoveHandler(i: number, newMove: Moves, move: Moves) {
|
||||||
const speciesId = this.lastSpecies.speciesId;
|
const speciesId = this.lastSpecies.speciesId;
|
||||||
const existingMoveIndex = this.starterMoveset?.indexOf(newMove)!; // TODO: is this bang correct?
|
const existingMoveIndex = this.starterMoveset?.indexOf(newMove)!; // TODO: is this bang correct?
|
||||||
@ -2099,9 +2108,24 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
// pre filter for challenges
|
// pre filter for challenges
|
||||||
if (this.scene.gameMode.modeId === GameModes.CHALLENGE) {
|
if (this.scene.gameMode.modeId === GameModes.CHALLENGE) {
|
||||||
this.starterContainers.forEach(container => {
|
this.starterContainers.forEach(container => {
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const species = container.species;
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(container.species, this.scene.gameData.getSpeciesDefaultDexAttr(container.species, false, true)), true);
|
let allFormsValid = false;
|
||||||
if (isValidForChallenge.value) {
|
if (species.forms?.length > 0) {
|
||||||
|
for (let i = 0; i < species.forms.length; i++) {
|
||||||
|
/* Here we are making a fake form index dex props for challenges
|
||||||
|
* Since some pokemon rely on forms to be valid (i.e. blaze tauros for fire challenges), we make a fake form and dex props to use in the challenge
|
||||||
|
*/
|
||||||
|
const tempFormProps = BigInt(Math.pow(2, i)) * DexAttr.DEFAULT_FORM;
|
||||||
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, tempFormProps), true);
|
||||||
|
allFormsValid = allFormsValid || isValidForChallenge.value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(container.species, false, true)), true);
|
||||||
|
allFormsValid = isValidForChallenge.value;
|
||||||
|
}
|
||||||
|
if (allFormsValid) {
|
||||||
this.validStarterContainers.push(container);
|
this.validStarterContainers.push(container);
|
||||||
} else {
|
} else {
|
||||||
container.setVisible(false);
|
container.setVisible(false);
|
||||||
@ -2111,6 +2135,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.validStarterContainers = this.starterContainers;
|
this.validStarterContainers = this.starterContainers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this updates icons for previously saved pokemon
|
||||||
|
for (let i = 0; i < this.validStarterContainers.length; i++) {
|
||||||
|
const currentFilteredContainer = this.validStarterContainers[i];
|
||||||
|
const starterSprite = currentFilteredContainer.icon as Phaser.GameObjects.Sprite;
|
||||||
|
|
||||||
|
const currentDexAttr = this.getCurrentDexProps(currentFilteredContainer.species.speciesId);
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(currentFilteredContainer.species, currentDexAttr);
|
||||||
|
|
||||||
|
starterSprite.setTexture(currentFilteredContainer.species.getIconAtlasKey(props.formIndex, props.shiny, props.variant), currentFilteredContainer.species.getIconId(props.female!, props.formIndex, props.shiny, props.variant));
|
||||||
|
currentFilteredContainer.checkIconId(props.female, props.formIndex, props.shiny, props.variant);
|
||||||
|
}
|
||||||
|
|
||||||
// filter
|
// filter
|
||||||
this.validStarterContainers.forEach(container => {
|
this.validStarterContainers.forEach(container => {
|
||||||
container.setVisible(false);
|
container.setVisible(false);
|
||||||
@ -2336,9 +2372,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
const species = this.filteredStarterContainers[cursor]?.species;
|
const species = this.filteredStarterContainers[cursor]?.species;
|
||||||
|
|
||||||
if (species) {
|
if (species) {
|
||||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
const variant = defaultProps.variant;
|
const variant = this.starterPreferences[species.speciesId]?.variant ? this.starterPreferences[species.speciesId].variant as Variant : defaultProps.variant;
|
||||||
const tint = getVariantTint(variant);
|
const tint = getVariantTint(variant);
|
||||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
||||||
this.pokemonShinyIcon.setTint(tint);
|
this.pokemonShinyIcon.setTint(tint);
|
||||||
@ -2384,7 +2420,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
setSpecies(species: PokemonSpecies | null) {
|
setSpecies(species: PokemonSpecies | null) {
|
||||||
this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null;
|
this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null;
|
||||||
this.dexAttrCursor = species ? this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true) : 0n;
|
this.dexAttrCursor = species ? this.getCurrentDexProps(species.speciesId) : 0n;
|
||||||
this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0;
|
this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0;
|
||||||
this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0;
|
this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0;
|
||||||
|
|
||||||
@ -2454,7 +2490,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastSpecies) {
|
if (this.lastSpecies) {
|
||||||
const dexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(this.lastSpecies, false, true);
|
const dexAttr = this.getCurrentDexProps(this.lastSpecies.speciesId);
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr);
|
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr);
|
||||||
const speciesIndex = this.allSpecies.indexOf(this.lastSpecies);
|
const speciesIndex = this.allSpecies.indexOf(this.lastSpecies);
|
||||||
const lastSpeciesIcon = this.starterContainers[speciesIndex].icon;
|
const lastSpeciesIcon = this.starterContainers[speciesIndex].icon;
|
||||||
@ -2480,7 +2516,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonLuckText.setText(luck.toString());
|
this.pokemonLuckText.setText(luck.toString());
|
||||||
this.pokemonLuckText.setTint(getVariantTint(Math.min(luck - 1, 2) as Variant));
|
this.pokemonLuckText.setTint(getVariantTint(Math.min(luck - 1, 2) as Variant));
|
||||||
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
||||||
this.pokemonShinyIcon.setVisible(this.pokemonLuckText.visible);
|
this.pokemonShinyIcon.setVisible(this.starterPreferences[species.speciesId]?.shiny ?? false);
|
||||||
|
|
||||||
//Growth translate
|
//Growth translate
|
||||||
let growthReadable = Utils.toReadableString(GrowthRate[species.growthRate]);
|
let growthReadable = Utils.toReadableString(GrowthRate[species.growthRate]);
|
||||||
@ -2504,7 +2540,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species));
|
this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species));
|
||||||
}
|
}
|
||||||
this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry.hatchedCount}`);
|
this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry.hatchedCount}`);
|
||||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
const variant = defaultProps.variant;
|
const variant = defaultProps.variant;
|
||||||
const tint = getVariantTint(variant);
|
const tint = getVariantTint(variant);
|
||||||
@ -2578,13 +2614,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
props = this.scene.gameData.getSpeciesDexAttrProps(species, this.starterAttr[starterIndex]);
|
props = this.scene.gameData.getSpeciesDexAttrProps(species, this.starterAttr[starterIndex]);
|
||||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, this.starterAbilityIndexes[starterIndex], this.starterNatures[starterIndex]);
|
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, this.starterAbilityIndexes[starterIndex], this.starterNatures[starterIndex]);
|
||||||
} else {
|
} else {
|
||||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||||
// load default nature from stater save data, if set
|
// load default nature from stater save data, if set
|
||||||
const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species);
|
const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species);
|
||||||
props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
if (starterAttributes?.variant && !isNaN(starterAttributes.variant)) {
|
if (starterAttributes?.variant && !isNaN(starterAttributes.variant)) {
|
||||||
if (props.shiny = (starterAttributes.variant >= 0)) {
|
if (props.shiny) {
|
||||||
props.variant = starterAttributes.variant as Variant;
|
props.variant = starterAttributes.variant as Variant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2679,6 +2715,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.dexAttrCursor |= this.scene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps!.formIndex)); // TODO: is this bang correct?
|
this.dexAttrCursor |= this.scene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps!.formIndex)); // TODO: is this bang correct?
|
||||||
this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex);
|
this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex);
|
||||||
this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex);
|
this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex);
|
||||||
|
const [isInParty, partyIndex]: [boolean, number] = this.isInParty(species); // we use this to firstly check if the pokemon is in the party, and if so, to get the party index in order to update the icon image
|
||||||
|
if (isInParty) {
|
||||||
|
this.updatePartyIcon(species, partyIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pokemonSprite.setVisible(false);
|
this.pokemonSprite.setVisible(false);
|
||||||
@ -2695,7 +2735,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
const dexEntry = this.scene.gameData.dexData[species.speciesId];
|
const dexEntry = this.scene.gameData.dexData[species.speciesId];
|
||||||
const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr;
|
const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr;
|
||||||
if (!dexEntry.caughtAttr) {
|
if (!dexEntry.caughtAttr) {
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, forSeen, !forSeen));
|
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 (shiny === undefined || shiny !== props.shiny) {
|
if (shiny === undefined || shiny !== props.shiny) {
|
||||||
@ -2750,9 +2790,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterSpecies.length);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterSpecies.length);
|
||||||
const starterSprite = this.filteredStarterContainers[this.cursor].icon as Phaser.GameObjects.Sprite;
|
const currentFilteredContainer = this.filteredStarterContainers.find(p => p.species.speciesId === species.speciesId)!;
|
||||||
starterSprite.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female!, formIndex, shiny, variant)); // TODO: is this bang correct?
|
const starterSprite = currentFilteredContainer.icon as Phaser.GameObjects.Sprite;
|
||||||
this.filteredStarterContainers[this.cursor].checkIconId(female, formIndex, shiny, variant);
|
starterSprite.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female!, formIndex, shiny, variant));
|
||||||
|
currentFilteredContainer.checkIconId(female, formIndex, shiny, variant);
|
||||||
this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY);
|
this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY);
|
||||||
this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE);
|
this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE);
|
||||||
this.canCycleAbility = [ abilityAttr & AbilityAttr.ABILITY_1, (abilityAttr & AbilityAttr.ABILITY_2) && species.ability2, abilityAttr & AbilityAttr.ABILITY_HIDDEN ].filter(a => a).length > 1;
|
this.canCycleAbility = [ abilityAttr & AbilityAttr.ABILITY_1, (abilityAttr & AbilityAttr.ABILITY_2) && species.ability2, abilityAttr & AbilityAttr.ABILITY_HIDDEN ].filter(a => a).length > 1;
|
||||||
@ -2876,6 +2917,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonAdditionalMoveCountLabel.setText(`(+${Math.max(this.speciesStarterMoves.length - 4, 0)})`);
|
this.pokemonAdditionalMoveCountLabel.setText(`(+${Math.max(this.speciesStarterMoves.length - 4, 0)})`);
|
||||||
this.pokemonAdditionalMoveCountLabel.setVisible(this.speciesStarterMoves.length > 4);
|
this.pokemonAdditionalMoveCountLabel.setVisible(this.speciesStarterMoves.length > 4);
|
||||||
|
|
||||||
|
this.tryUpdateValue();
|
||||||
|
|
||||||
this.updateInstructions();
|
this.updateInstructions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2903,7 +2946,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
for (let s = 0; s < this.starterSpecies.length; s++) {
|
for (let s = 0; s < this.starterSpecies.length; s++) {
|
||||||
const species = this.starterSpecies[s];
|
const species = this.starterSpecies[s];
|
||||||
const currentDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const currentDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, currentDexAttr);
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, currentDexAttr);
|
||||||
this.starterIcons[s].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
|
this.starterIcons[s].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
|
||||||
this.starterIcons[s].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
this.starterIcons[s].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
||||||
@ -2984,7 +3027,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
if (addingToParty) { // this does a check to see if the pokemon being added is valid; if so, it will update the isPartyValid boolean
|
if (addingToParty) { // this does a check to see if the pokemon being added is valid; if so, it will update the isPartyValid boolean
|
||||||
const isNewPokemonValid = new Utils.BooleanHolder(true);
|
const isNewPokemonValid = new Utils.BooleanHolder(true);
|
||||||
const species = this.filteredStarterContainers[this.cursor].species;
|
const species = this.filteredStarterContainers[this.cursor].species;
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isNewPokemonValid, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true)), !!(this.starterSpecies.length), false, false);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isNewPokemonValid, this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)), false);
|
||||||
isPartyValid = isPartyValid || isNewPokemonValid.value;
|
isPartyValid = isPartyValid || isNewPokemonValid.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3013,11 +3056,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
* we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too.
|
* we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too.
|
||||||
*/
|
*/
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
if (isPartyValid) { // we have two checks here - one for the party being valid and one for not. This comes from mono type challenges - if the party is valid it will check pokemon's evolutions and forms, and if it's not valid it won't check their evolutions and forms
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.allSpecies[s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.allSpecies[s], this.getCurrentDexProps(this.allSpecies[s].speciesId)), isPartyValid);
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.allSpecies[s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.allSpecies[s], this.scene.gameData.getSpeciesDefaultDexAttr(this.allSpecies[s], false, true)), !!(this.starterSpecies.length + (add ? 1 : 0)));
|
|
||||||
} else {
|
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.allSpecies[s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.allSpecies[s], this.scene.gameData.getSpeciesDefaultDexAttr(this.allSpecies[s], false, true)), !!(this.starterSpecies.length + (add ? 1 : 0)), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value;
|
const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value;
|
||||||
|
|
||||||
@ -3132,12 +3171,50 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
for (let s = 0; s < this.starterSpecies.length; s++) {
|
for (let s = 0; s < this.starterSpecies.length; s++) {
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
const species = this.starterSpecies[s];
|
const species = this.starterSpecies[s];
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), this.starterSpecies.length !== 0, false, false);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)), false);
|
||||||
canStart = canStart || isValidForChallenge.value;
|
canStart = canStart || isValidForChallenge.value;
|
||||||
}
|
}
|
||||||
return canStart;
|
return canStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this creates a temporary dex attr props that we use to check whether a pokemon is valid for a challenge.
|
||||||
|
* when checking for certain challenges (i.e. mono type), we need to check for form changes AND evolutions
|
||||||
|
* However, since some pokemon can evolve based on their intial gender/form, we need a way to look for that
|
||||||
|
* This temporary dex attr will therefore ONLY look at gender and form, since there's no cases of shinies/variants
|
||||||
|
* having different evolutions to their non shiny/variant part, and so those can be ignored
|
||||||
|
* Since the current form and gender is stored in the starter preferences, this is where we get the values from
|
||||||
|
*/
|
||||||
|
getCurrentDexProps(speciesId: number): bigint {
|
||||||
|
let props = 0n;
|
||||||
|
|
||||||
|
if (this.starterPreferences[speciesId]?.female) { // this checks the gender of the pokemon
|
||||||
|
props += DexAttr.FEMALE;
|
||||||
|
} else {
|
||||||
|
props += DexAttr.MALE;
|
||||||
|
}
|
||||||
|
if (this.starterPreferences[speciesId]?.shiny) {
|
||||||
|
props += DexAttr.SHINY;
|
||||||
|
if (this.starterPreferences[speciesId]?.variant) {
|
||||||
|
props += BigInt(Math.pow(2, this.starterPreferences[speciesId]?.variant)) * DexAttr.DEFAULT_VARIANT;
|
||||||
|
} else {
|
||||||
|
props += DexAttr.DEFAULT_VARIANT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
props += DexAttr.NON_SHINY;
|
||||||
|
if (this.starterPreferences[speciesId]?.variant) {
|
||||||
|
delete this.starterPreferences[speciesId].variant;
|
||||||
|
}
|
||||||
|
props += DexAttr.DEFAULT_VARIANT; // we add the default variant here because non shiny versions are listed as default variant
|
||||||
|
}
|
||||||
|
if (this.starterPreferences[speciesId]?.form) { // this checks for the form of the pokemon
|
||||||
|
props += BigInt(Math.pow(2, this.starterPreferences[speciesId]?.form)) * DexAttr.DEFAULT_FORM;
|
||||||
|
} else {
|
||||||
|
props += DexAttr.DEFAULT_FORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
toggleStatsMode(on?: boolean): void {
|
toggleStatsMode(on?: boolean): void {
|
||||||
if (on === undefined) {
|
if (on === undefined) {
|
||||||
on = !this.statsMode;
|
on = !this.statsMode;
|
||||||
|
Loading…
Reference in New Issue
Block a user