Compare commits

..

No commits in common. "0221c9fabad05c134e1c3d2c19fc0c50a2310a7d" and "72702abb2ff0aa2902b13345cc8e6fc907d46451" have entirely different histories.

52 changed files with 1078 additions and 1833 deletions

View File

@ -8,7 +8,7 @@ import { Weather, WeatherType } from "./weather";
import { BattlerTag, GroundedTag, GulpMissileTag, SemiInvulnerableTag } from "./battler-tags";
import { StatusEffect, getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "./status-effect";
import { Gender } from "./gender";
import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, FlinchAttr, OneHitKOAttr, HitHealAttr, allMoves, StatusMove, SelfStatusMove, VariablePowerAttr, applyMoveAttrs, IncrementMovePriorityAttr, VariableMoveTypeAttr, RandomMovesetMoveAttr, RandomMoveAttr, NaturePowerAttr, CopyMoveAttr, MoveAttr, MultiHitAttr, ChargeAttr, SacrificialAttr, SacrificialAttrOnHit, NeutralDamageAgainstFlyingTypeMultiplierAttr } from "./move";
import Move, { AttackMove, MoveCategory, MoveFlags, MoveTarget, FlinchAttr, OneHitKOAttr, HitHealAttr, allMoves, StatusMove, SelfStatusMove, VariablePowerAttr, applyMoveAttrs, IncrementMovePriorityAttr, VariableMoveTypeAttr, RandomMovesetMoveAttr, RandomMoveAttr, NaturePowerAttr, CopyMoveAttr, MoveAttr, MultiHitAttr, ChargeAttr, SacrificialAttr, SacrificialAttrOnHit } from "./move";
import { ArenaTagSide, ArenaTrapTag } from "./arena-tag";
import { Stat, getStatName } from "./pokemon-stat";
import { BerryModifier, PokemonHeldItemModifier } from "../modifier/modifier";
@ -349,7 +349,7 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr {
if ([ MoveTarget.BOTH_SIDES, MoveTarget.ENEMY_SIDE, MoveTarget.USER_SIDE ].includes(move.moveTarget)) {
return false;
}
if (attacker !== pokemon && attacker.getMoveType(move) === this.immuneType) {
if (attacker !== pokemon && move.type === this.immuneType) {
(args[0] as Utils.NumberHolder).value = 0;
return true;
}
@ -372,8 +372,7 @@ export class AttackTypeImmunityAbAttr extends TypeImmunityAbAttr {
* Example: Levitate
*/
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
// this is a hacky way to fix the Levitate/Thousand Arrows interaction, but it works for now...
if (move.category !== MoveCategory.STATUS && !move.hasAttr(NeutralDamageAgainstFlyingTypeMultiplierAttr)) {
if (move.category !== MoveCategory.STATUS) {
return super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args);
}
return false;
@ -393,7 +392,6 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr {
const abilityName = (!passive ? pokemon.getAbility() : pokemon.getPassiveAbility()).name;
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
Utils.toDmgValue(pokemon.getMaxHp() / 4), i18next.t("abilityTriggers:typeImmunityHeal", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName }), true));
cancelled.value = true; // Suppresses "No Effect" message
}
return true;
}
@ -417,7 +415,7 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr {
const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args);
if (ret) {
cancelled.value = true; // Suppresses "No Effect" message
cancelled.value = true;
if (!simulated) {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels));
}
@ -442,7 +440,7 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr {
const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args);
if (ret) {
cancelled.value = true; // Suppresses "No Effect" message
cancelled.value = true;
if (!simulated) {
pokemon.addTag(this.tagType, this.turnCount, undefined, pokemon.id);
}
@ -458,8 +456,8 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr {
}
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (move instanceof AttackMove && pokemon.getAttackTypeEffectiveness(pokemon.getMoveType(move), attacker) < 2) {
cancelled.value = true; // Suppresses "No Effect" message
if (move instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.type, attacker) < 2) {
cancelled.value = true;
(args[0] as Utils.NumberHolder).value = 0;
return true;
}
@ -766,7 +764,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
if (simulated) {
return true;
}
const type = attacker.getMoveType(move);
const type = move.type;
const pokemonTypes = pokemon.getTypes(true);
if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) {
pokemon.summonData.types = [ type ];
@ -1214,7 +1212,7 @@ export class FieldMultiplyBattleStatAbAttr extends AbAttr {
}
export class MoveTypeChangeAbAttr extends PreAttackAbAttr {
export class MoveTypeChangeAttr extends PreAttackAbAttr {
constructor(
private newType: Type,
private powerMultiplier: number,
@ -1223,14 +1221,11 @@ export class MoveTypeChangeAbAttr extends PreAttackAbAttr {
super(true);
}
// TODO: Decouple this into two attributes (type change / power boost)
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
if (this.condition && this.condition(pokemon, defender, move)) {
move.type = this.newType;
if (args[0] && args[0] instanceof Utils.NumberHolder) {
args[0].value = this.newType;
}
if (args[1] && args[1] instanceof Utils.NumberHolder) {
args[1].value *= this.powerMultiplier;
args[0].value *= this.powerMultiplier;
}
return true;
}
@ -1262,12 +1257,22 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
attr instanceof CopyMoveAttr
)
) {
const moveType = pokemon.getMoveType(move);
// TODO remove this copy when phase order is changed so that damage, type, category, etc.
// TODO are all calculated prior to playing the move animation.
const moveCopy = new Move(move.id, move.type, move.category, move.moveTarget, move.power, move.accuracy, move.pp, move.chance, move.priority, move.generation);
moveCopy.attrs = move.attrs;
if (pokemon.getTypes().some((t) => t !== moveType)) {
// Moves like Weather Ball ignore effects of abilities like Normalize and Refrigerate
if (move.findAttr(attr => attr instanceof VariableMoveTypeAttr)) {
applyMoveAttrs(VariableMoveTypeAttr, pokemon, null, moveCopy);
} else {
applyPreAttackAbAttrs(MoveTypeChangeAttr, pokemon, null, moveCopy);
}
if (pokemon.getTypes().some((t) => t !== moveCopy.type)) {
if (!simulated) {
this.moveType = moveType;
pokemon.summonData.types = [moveType];
this.moveType = moveCopy.type;
pokemon.summonData.types = [moveCopy.type];
pokemon.updateInfo();
}
@ -2973,20 +2978,16 @@ function getAnticipationCondition(): AbAttrCondition {
return (pokemon: Pokemon) => {
for (const opponent of pokemon.getOpponents()) {
for (const move of opponent.moveset) {
// ignore null/undefined moves
if (!move) {
continue;
}
// the move's base type (not accounting for variable type changes) is super effective
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent, true) >= 2) {
// move is super effective
if (move!.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move!.getMove().type, opponent, true) >= 2) { // TODO: is this bang correct?
return true;
}
// move is a OHKO
if (move.getMove().hasAttr(OneHitKOAttr)) {
if (move?.getMove().hasAttr(OneHitKOAttr)) {
return true;
}
// edge case for hidden power, type is computed
if (move.getMove().id === Moves.HIDDEN_POWER) {
if (move?.getMove().id === Moves.HIDDEN_POWER) {
const iv_val = Math.floor(((opponent.ivs[Stat.HP] & 1)
+(opponent.ivs[Stat.ATK] & 1) * 2
+(opponent.ivs[Stat.DEF] & 1) * 4
@ -5018,7 +5019,7 @@ export function initAbilities() {
.conditionalAttr(pokemon => pokemon.status ? pokemon.status.effect === StatusEffect.PARALYSIS : false, BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
.conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), BattleStatMultiplierAbAttr, BattleStat.SPD, 1.5),
new Ability(Abilities.NORMALIZE, 4)
.attr(MoveTypeChangeAbAttr, Type.NORMAL, 1.2, (user, target, move) => {
.attr(MoveTypeChangeAttr, Type.NORMAL, 1.2, (user, target, move) => {
return ![Moves.HIDDEN_POWER, Moves.WEATHER_BALL, Moves.NATURAL_GIFT, Moves.JUDGMENT, Moves.TECHNO_BLAST].includes(move.id);
}),
new Ability(Abilities.SNIPER, 4)
@ -5259,7 +5260,7 @@ export function initAbilities() {
new Ability(Abilities.STRONG_JAW, 6)
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5),
new Ability(Abilities.REFRIGERATE, 6)
.attr(MoveTypeChangeAbAttr, Type.ICE, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
.attr(MoveTypeChangeAttr, Type.ICE, 1.2, (user, target, move) => move.type === Type.NORMAL),
new Ability(Abilities.SWEET_VEIL, 6)
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.SLEEP)
.attr(UserFieldBattlerTagImmunityAbAttr, BattlerTagType.DROWSY)
@ -5282,11 +5283,11 @@ export function initAbilities() {
new Ability(Abilities.TOUGH_CLAWS, 6)
.attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 1.3),
new Ability(Abilities.PIXILATE, 6)
.attr(MoveTypeChangeAbAttr, Type.FAIRY, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
.attr(MoveTypeChangeAttr, Type.FAIRY, 1.2, (user, target, move) => move.type === Type.NORMAL),
new Ability(Abilities.GOOEY, 6)
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), BattleStat.SPD, -1, false),
new Ability(Abilities.AERILATE, 6)
.attr(MoveTypeChangeAbAttr, Type.FLYING, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
.attr(MoveTypeChangeAttr, Type.FLYING, 1.2, (user, target, move) => move.type === Type.NORMAL),
new Ability(Abilities.PARENTAL_BOND, 6)
.attr(AddSecondStrikeAbAttr, 0.25),
new Ability(Abilities.DARK_AURA, 6)
@ -5358,11 +5359,11 @@ export function initAbilities() {
new Ability(Abilities.LONG_REACH, 7)
.attr(IgnoreContactAbAttr),
new Ability(Abilities.LIQUID_VOICE, 7)
.attr(MoveTypeChangeAbAttr, Type.WATER, 1, (user, target, move) => move.hasFlag(MoveFlags.SOUND_BASED)),
.attr(MoveTypeChangeAttr, Type.WATER, 1, (user, target, move) => move.hasFlag(MoveFlags.SOUND_BASED)),
new Ability(Abilities.TRIAGE, 7)
.attr(ChangeMovePriorityAbAttr, (pokemon, move) => move.hasFlag(MoveFlags.TRIAGE_MOVE), 3),
new Ability(Abilities.GALVANIZE, 7)
.attr(MoveTypeChangeAbAttr, Type.ELECTRIC, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
.attr(MoveTypeChangeAttr, Type.ELECTRIC, 1.2, (user, target, move) => move.type === Type.NORMAL),
new Ability(Abilities.SURGE_SURFER, 7)
.conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), BattleStatMultiplierAbAttr, BattleStat.SPD, 2),
new Ability(Abilities.SCHOOLING, 7)

View File

@ -9,7 +9,7 @@ import { Constructor } from "#app/utils";
import * as Utils from "../utils";
import { WeatherType } from "./weather";
import { ArenaTagSide, ArenaTrapTag, WeakenMoveTypeTag } from "./arena-tag";
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, WonderSkinAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAbAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability";
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, WonderSkinAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability";
import { allAbilities } from "./ability";
import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier, PokemonMoveAccuracyBoosterModifier, AttackTypeBoosterModifier, PokemonMultiHitModifier } from "../modifier/modifier";
import { BattlerIndex, BattleType } from "../battle";
@ -113,8 +113,9 @@ type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean;
export default class Move implements Localizable {
public id: Moves;
public name: string;
private _type: Type;
private _category: MoveCategory;
public type: Type;
public defaultType: Type;
public category: MoveCategory;
public moveTarget: MoveTarget;
public power: integer;
public accuracy: integer;
@ -132,8 +133,9 @@ export default class Move implements Localizable {
this.id = id;
this.nameAppend = "";
this._type = type;
this._category = category;
this.type = type;
this.defaultType = type;
this.category = category;
this.moveTarget = defaultMoveTarget;
this.power = power;
this.accuracy = accuracy;
@ -156,13 +158,6 @@ export default class Move implements Localizable {
this.localize();
}
get type() {
return this._type;
}
get category() {
return this._category;
}
localize(): void {
const i18nKey = Moves[this.id].split("_").filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join("") as unknown as string;
@ -738,7 +733,7 @@ export default class Move implements Localizable {
const power = new Utils.NumberHolder(this.power);
const typeChangeMovePowerMultiplier = new Utils.NumberHolder(1);
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, source, target, this, true, null, typeChangeMovePowerMultiplier);
applyPreAttackAbAttrs(MoveTypeChangeAttr, source, target, this, simulated, typeChangeMovePowerMultiplier);
const sourceTeraType = source.getTeraType();
if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr(MultiHitAttr) && !source.scene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) {
@ -1088,12 +1083,15 @@ export class PreMoveMessageAttr extends MoveAttr {
}
}
/**
* Attribute for Status moves that take attack type effectiveness
* into consideration (i.e. {@linkcode https://bulbapedia.bulbagarden.net/wiki/Thunder_Wave_(move) | Thunder Wave})
* @extends MoveAttr
*/
export class RespectAttackTypeImmunityAttr extends MoveAttr { }
export class StatusMoveTypeImmunityAttr extends MoveAttr {
public immuneType: Type;
constructor(immuneType: Type) {
super(false);
this.immuneType = immuneType;
}
}
export class IgnoreOpponentStatChangesAttr extends MoveAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -1853,11 +1851,19 @@ export class MultiHitAttr extends MoveAttr {
* @returns True
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const hitType = new Utils.NumberHolder(this.multiHitType);
applyMoveAttrs(ChangeMultiHitTypeAttr, user, target, move, hitType);
this.multiHitType = hitType.value;
let hitTimes: integer;
(args[0] as Utils.NumberHolder).value = this.getHitCount(user, target);
if (target.getAttackMoveEffectiveness(user, new PokemonMove(move.id)) === 0) {
// If there is a type immunity, the attack will stop no matter what
hitTimes = 1;
} else {
const hitType = new Utils.IntegerHolder(this.multiHitType);
applyMoveAttrs(ChangeMultiHitTypeAttr, user, target, move, hitType);
this.multiHitType = hitType.value;
hitTimes = this.getHitCount(user, target);
}
(args[0] as Utils.IntegerHolder).value = hitTimes;
return true;
}
@ -3756,7 +3762,7 @@ export class VariableMoveCategoryAttr extends MoveAttr {
export class PhotonGeyserCategoryAttr extends VariableMoveCategoryAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const category = (args[0] as Utils.NumberHolder);
const category = (args[0] as Utils.IntegerHolder);
if (user.getBattleStat(Stat.ATK, target, move) > user.getBattleStat(Stat.SPATK, target, move)) {
category.value = MoveCategory.PHYSICAL;
@ -3769,7 +3775,7 @@ export class PhotonGeyserCategoryAttr extends VariableMoveCategoryAttr {
export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const category = (args[0] as Utils.NumberHolder);
const category = (args[0] as Utils.IntegerHolder);
if (user.isTerastallized() && user.getBattleStat(Stat.ATK, target, move) > user.getBattleStat(Stat.SPATK, target, move)) {
category.value = MoveCategory.PHYSICAL;
@ -3785,21 +3791,18 @@ export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr {
* @extends VariablePowerAttr
*/
export class TeraBlastPowerAttr extends VariablePowerAttr {
/**
* Sets Tera Blast's power to 100 if the user is terastallized with
* the Stellar tera type.
* @param user {@linkcode Pokemon} the Pokemon using this move
* @param target n/a
* @param move {@linkcode Move} the Move with this attribute (i.e. Tera Blast)
* @param args
* - [0] {@linkcode Utils.NumberHolder} the applied move's power, factoring in
* previously applied power modifiers.
* @returns
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
/**
* @param user {@linkcode Pokemon} Pokemon using the move
* @param target {@linkcode Pokemon} N/A
* @param move {@linkcode Move} {@linkcode Move.TERA_BLAST}
* @param {any[]} args N/A
* @returns true or false
*/
const power = args[0] as Utils.NumberHolder;
if (user.isTerastallized() && user.getTeraType() === Type.STELLAR) {
power.value = 100;
if (user.isTerastallized() && move.type === Type.STELLAR) {
//200 instead of 100 to reflect lack of stellar being 2x dmg on any type
power.value = 200;
return true;
}
@ -3859,15 +3862,10 @@ export class VariableMoveTypeAttr extends MoveAttr {
export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.ARCEUS) || [user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.SILVALLY)) {
const form = user.species.speciesId === Species.ARCEUS || user.species.speciesId === Species.SILVALLY ? user.formIndex : user.fusionSpecies?.formIndex!; // TODO: is this bang correct?
moveType.value = Type[Type[form]];
move.type = Type[Type[form]];
return true;
}
@ -3877,29 +3875,24 @@ export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
export class TechnoBlastTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.GENESECT)) {
const form = user.species.speciesId === Species.GENESECT ? user.formIndex : user.fusionSpecies?.formIndex;
switch (form) {
case 1: // Shock Drive
moveType.value = Type.ELECTRIC;
move.type = Type.ELECTRIC;
break;
case 2: // Burn Drive
moveType.value = Type.FIRE;
move.type = Type.FIRE;
break;
case 3: // Chill Drive
moveType.value = Type.ICE;
move.type = Type.ICE;
break;
case 4: // Douse Drive
moveType.value = Type.WATER;
move.type = Type.WATER;
break;
default:
moveType.value = Type.NORMAL;
move.type = Type.NORMAL;
break;
}
return true;
@ -3911,20 +3904,15 @@ export class TechnoBlastTypeAttr extends VariableMoveTypeAttr {
export class AuraWheelTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.MORPEKO)) {
const form = user.species.speciesId === Species.MORPEKO ? user.formIndex : user.fusionSpecies?.formIndex;
switch (form) {
case 1: // Hangry Mode
moveType.value = Type.DARK;
move.type = Type.DARK;
break;
default: // Full Belly Mode
moveType.value = Type.ELECTRIC;
move.type = Type.ELECTRIC;
break;
}
return true;
@ -3936,23 +3924,18 @@ export class AuraWheelTypeAttr extends VariableMoveTypeAttr {
export class RagingBullTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.PALDEA_TAUROS)) {
const form = user.species.speciesId === Species.PALDEA_TAUROS ? user.formIndex : user.fusionSpecies?.formIndex;
switch (form) {
case 1: // Blaze breed
moveType.value = Type.FIRE;
move.type = Type.FIRE;
break;
case 2: // Aqua breed
moveType.value = Type.WATER;
move.type = Type.WATER;
break;
default:
moveType.value = Type.FIGHTING;
move.type = Type.FIGHTING;
break;
}
return true;
@ -3964,30 +3947,25 @@ export class RagingBullTypeAttr extends VariableMoveTypeAttr {
export class IvyCudgelTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.OGERPON)) {
const form = user.species.speciesId === Species.OGERPON ? user.formIndex : user.fusionSpecies?.formIndex;
switch (form) {
case 1: // Wellspring Mask
case 5: // Wellspring Mask Tera
moveType.value = Type.WATER;
move.type = Type.WATER;
break;
case 2: // Hearthflame Mask
case 6: // Hearthflame Mask Tera
moveType.value = Type.FIRE;
move.type = Type.FIRE;
break;
case 3: // Cornerstone Mask
case 7: // Cornerstone Mask Tera
moveType.value = Type.ROCK;
move.type = Type.ROCK;
break;
case 4: // Teal Mask Tera
default:
moveType.value = Type.GRASS;
move.type = Type.GRASS;
break;
}
return true;
@ -3999,27 +3977,22 @@ export class IvyCudgelTypeAttr extends VariableMoveTypeAttr {
export class WeatherBallTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) {
switch (user.scene.arena.weather?.weatherType) {
case WeatherType.SUNNY:
case WeatherType.HARSH_SUN:
moveType.value = Type.FIRE;
move.type = Type.FIRE;
break;
case WeatherType.RAIN:
case WeatherType.HEAVY_RAIN:
moveType.value = Type.WATER;
move.type = Type.WATER;
break;
case WeatherType.SANDSTORM:
moveType.value = Type.ROCK;
move.type = Type.ROCK;
break;
case WeatherType.HAIL:
case WeatherType.SNOW:
moveType.value = Type.ICE;
move.type = Type.ICE;
break;
default:
return false;
@ -4042,15 +4015,10 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
* @param user {@linkcode Pokemon} using this move
* @param target N/A
* @param move N/A
* @param args [0] {@linkcode Utils.NumberHolder} The move's type to be modified
* @param args [0] {@linkcode Utils.IntegerHolder} The move's type to be modified
* @returns true if the function succeeds
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
if (!user.isGrounded()) {
return false;
}
@ -4058,16 +4026,16 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
const currentTerrain = user.scene.arena.getTerrainType();
switch (currentTerrain) {
case TerrainType.MISTY:
moveType.value = Type.FAIRY;
move.type = Type.FAIRY;
break;
case TerrainType.ELECTRIC:
moveType.value = Type.ELECTRIC;
move.type = Type.ELECTRIC;
break;
case TerrainType.GRASSY:
moveType.value = Type.GRASS;
move.type = Type.GRASS;
break;
case TerrainType.PSYCHIC:
moveType.value = Type.PSYCHIC;
move.type = Type.PSYCHIC;
break;
default:
return false;
@ -4076,17 +4044,8 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
}
}
/**
* Changes type based on the user's IVs
* @extends VariableMoveTypeAttr
*/
export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
const iv_val = Math.floor(((user.ivs[Stat.HP] & 1)
+(user.ivs[Stat.ATK] & 1) * 2
+(user.ivs[Stat.DEF] & 1) * 4
@ -4094,7 +4053,7 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
+(user.ivs[Stat.SPATK] & 1) * 16
+(user.ivs[Stat.SPDEF] & 1) * 32) * 15/63);
moveType.value = [
move.type = [
Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND,
Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL,
Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC,
@ -4109,21 +4068,16 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
* @extends VariableMoveTypeAttr
*/
export class TeraBlastTypeAttr extends VariableMoveTypeAttr {
/**
* @param user {@linkcode Pokemon} the user of the move
* @param target {@linkcode Pokemon} N/A
* @param move {@linkcode Move} the move with this attribute
* @param args `[0]` the move's type to be modified
* @returns `true` if the move's type was modified; `false` otherwise
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
/**
* @param user {@linkcode Pokemon} the user's type is checked
* @param target {@linkcode Pokemon} N/A
* @param move {@linkcode Move} {@linkcode Move.TeraBlastTypeAttr}
* @param {any[]} args N/A
* @returns true or false
*/
if (user.isTerastallized()) {
moveType.value = user.getTeraType(); // changes move type to tera type
move.type = user.getTeraType(); //changes move type to tera type
return true;
}
@ -4133,18 +4087,14 @@ export class TeraBlastTypeAttr extends VariableMoveTypeAttr {
export class MatchUserTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const moveType = args[0];
if (!(moveType instanceof Utils.NumberHolder)) {
return false;
}
const userTypes = user.getTypes(true);
if (userTypes.includes(Type.STELLAR)) { // will not change to stellar type
const nonTeraTypes = user.getTypes();
moveType.value = nonTeraTypes[0];
move.type = nonTeraTypes[0];
return true;
} else if (userTypes.length > 0) {
moveType.value = userTypes[0];
move.type = userTypes[0];
return true;
} else {
return false;
@ -4163,8 +4113,8 @@ export class NeutralDamageAgainstFlyingTypeMultiplierAttr extends VariableMoveTy
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!target.getTag(BattlerTagType.IGNORE_FLYING)) {
const multiplier = args[0] as Utils.NumberHolder;
//When a flying type is hit, the first hit is always 1x multiplier.
if (target.isOfType(Type.FLYING)) {
//When a flying type is hit, the first hit is always 1x multiplier. Levitating pokemon are instantly affected by typing
if (target.isOfType(Type.FLYING) || target.hasAbility(Abilities.LEVITATE)) {
multiplier.value = 1;
}
return true;
@ -6555,7 +6505,7 @@ export function initMoves() {
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
new StatusMove(Moves.THUNDER_WAVE, Type.ELECTRIC, 90, 20, -1, 0, 1)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
.attr(RespectAttackTypeImmunityAttr),
.attr(StatusMoveTypeImmunityAttr, Type.GROUND),
new AttackMove(Moves.THUNDER, Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, 30, 0, 1)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
.attr(ThunderAccuracyAttr)
@ -8395,8 +8345,8 @@ export function initMoves() {
.partial()
.ignoresVirtual(),
/* End Unused */
new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 50, 100, 15, 100, 2, 7) //LGPE Implementation
.attr(CritOnlyAttr),
new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 100, 2, 7)
.attr(StatChangeAttr, BattleStat.EVA, 1, true),
new AttackMove(Moves.SPLISHY_SPLASH, Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, 30, 0, 7)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
.target(MoveTarget.ALL_NEAR_ENEMIES),
@ -8682,6 +8632,7 @@ export function initMoves() {
.attr(StatusEffectAttr, StatusEffect.BURN),
new StatusMove(Moves.JUNGLE_HEALING, Type.GRASS, -1, 10, -1, 0, 8)
.attr(HealAttr, 0.25, true, false)
.attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP)
.attr(HealStatusEffectAttr, false, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP)
.target(MoveTarget.USER_AND_ALLIES),
new AttackMove(Moves.WICKED_BLOW, Type.DARK, MoveCategory.PHYSICAL, 75, 100, 5, -1, 0, 8)
@ -8785,7 +8736,8 @@ export function initMoves() {
.windMove()
.target(MoveTarget.ALL_NEAR_ENEMIES),
new StatusMove(Moves.LUNAR_BLESSING, Type.PSYCHIC, -1, 5, -1, 0, 8)
.attr(HealAttr, 0.25, true, false)
.attr(HealAttr, 0.25)
.attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP)
.attr(HealStatusEffectAttr, false, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP)
.target(MoveTarget.USER_AND_ALLIES)
.triageMove(),

View File

@ -18800,85 +18800,6 @@ export const pokemonFormLevelMoves: PokemonSpeciesFormLevelMoves = {
[ 44, Moves.THUNDER ],
[ 48, Moves.PIKA_PAPOW ],
],
8: [
[ 1, Moves.TAIL_WHIP ],
[ 1, Moves.GROWL ],
[ 1, Moves.THUNDER_SHOCK ],
[ 1, Moves.QUICK_ATTACK ],
[ 1, Moves.SWEET_KISS ],
[ 1, Moves.CHARM ],
[ 1, Moves.NASTY_PLOT ],
[ 1, Moves.PLAY_NICE ],
[ 1, Moves.NUZZLE ],
[ 4, Moves.THUNDER_WAVE ],
[ 8, Moves.DOUBLE_TEAM ],
[ 12, Moves.ELECTRO_BALL ],
[ 16, Moves.FEINT ],
[ 20, Moves.ZIPPY_ZAP ], //Custom
[ 24, Moves.AGILITY ],
[ 28, Moves.IRON_TAIL ],
[ 32, Moves.DISCHARGE ],
[ 34, Moves.FLOATY_FALL ], //Custom
[ 36, Moves.THUNDERBOLT ],
[ 40, Moves.LIGHT_SCREEN ],
[ 42, Moves.SPLISHY_SPLASH ], //Custom
[ 44, Moves.THUNDER ],
[ 48, Moves.PIKA_PAPOW ],
],
},
[Species.EEVEE]: { //Custom
1: [
[ 1, Moves.TACKLE ],
[ 1, Moves.TAIL_WHIP ],
[ 1, Moves.GROWL ],
[ 1, Moves.HELPING_HAND ],
[ 1, Moves.COVET ],
[ 5, Moves.SAND_ATTACK ],
[ 10, Moves.QUICK_ATTACK ],
[ 15, Moves.BABY_DOLL_EYES ],
[ 18, Moves.BOUNCY_BUBBLE ], //Custom
[ 18, Moves.SIZZLY_SLIDE ], //Custom
[ 18, Moves.BUZZY_BUZZ ], //Custom
[ 20, Moves.SWIFT ],
[ 25, Moves.BITE ],
[ 30, Moves.COPYCAT ],
[ 33, Moves.BADDY_BAD ], //Custom
[ 33, Moves.GLITZY_GLOW ], //Custom
[ 35, Moves.BATON_PASS ],
[ 40, Moves.VEEVEE_VOLLEY ], //Custom, replaces Take Down
[ 43, Moves.FREEZY_FROST ], //Custom
[ 43, Moves.SAPPY_SEED ], //Custom
[ 45, Moves.CHARM ],
[ 50, Moves.DOUBLE_EDGE ],
[ 53, Moves.SPARKLY_SWIRL ], //Custom
[ 55, Moves.LAST_RESORT ],
],
2: [
[ 1, Moves.TACKLE ],
[ 1, Moves.TAIL_WHIP ],
[ 1, Moves.GROWL ],
[ 1, Moves.HELPING_HAND ],
[ 1, Moves.COVET ],
[ 5, Moves.SAND_ATTACK ],
[ 10, Moves.QUICK_ATTACK ],
[ 15, Moves.BABY_DOLL_EYES ],
[ 18, Moves.BOUNCY_BUBBLE ], //Custom
[ 18, Moves.SIZZLY_SLIDE ], //Custom
[ 18, Moves.BUZZY_BUZZ ], //Custom
[ 20, Moves.SWIFT ],
[ 25, Moves.BITE ],
[ 30, Moves.COPYCAT ],
[ 33, Moves.BADDY_BAD ], //Custom
[ 33, Moves.GLITZY_GLOW ], //Custom
[ 35, Moves.BATON_PASS ],
[ 40, Moves.VEEVEE_VOLLEY ], //Custom, replaces Take Down
[ 43, Moves.FREEZY_FROST ], //Custom
[ 43, Moves.SAPPY_SEED ], //Custom
[ 45, Moves.CHARM ],
[ 50, Moves.DOUBLE_EDGE ],
[ 53, Moves.SPARKLY_SWIRL ], //Custom
[ 55, Moves.LAST_RESORT ],
],
},
[Species.DEOXYS]: {
1: [

View File

@ -913,7 +913,7 @@ export function initSpecies() {
new PokemonSpecies(Species.VENUSAUR, 1, false, false, false, "Seed Pokémon", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, GrowthRate.MEDIUM_SLOW, 87.5, true, true,
new PokemonForm("Normal", "", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, true, null, true),
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GRASS, Type.POISON, 2.4, 155.5, Abilities.THICK_FAT, Abilities.THICK_FAT, Abilities.THICK_FAT, 625, 80, 100, 123, 122, 120, 80, 45, 50, 263, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.POISON, 24, 100, Abilities.CHLOROPHYLL, Abilities.CHLOROPHYLL, Abilities.CHLOROPHYLL, 625, 120, 82, 98, 130, 115, 80, 45, 50, 263, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.POISON, 24, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 625, 100, 90, 120, 110, 130, 75, 45, 50, 263, true),
),
new PokemonSpecies(Species.CHARMANDER, 1, false, false, false, "Lizard Pokémon", Type.FIRE, null, 0.6, 8.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 309, 39, 52, 43, 60, 50, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.CHARMELEON, 1, false, false, false, "Flame Pokémon", Type.FIRE, null, 1.1, 19, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 405, 58, 64, 58, 80, 65, 80, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false),
@ -921,20 +921,20 @@ export function initSpecies() {
new PokemonForm("Normal", "", Type.FIRE, Type.FLYING, 1.7, 90.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 534, 78, 84, 78, 109, 85, 100, 45, 50, 267, false, null, true),
new PokemonForm("Mega X", SpeciesFormKey.MEGA_X, Type.FIRE, Type.DRAGON, 1.7, 110.5, Abilities.TOUGH_CLAWS, Abilities.NONE, Abilities.TOUGH_CLAWS, 634, 78, 130, 111, 130, 85, 100, 45, 50, 267),
new PokemonForm("Mega Y", SpeciesFormKey.MEGA_Y, Type.FIRE, Type.FLYING, 1.7, 100.5, Abilities.DROUGHT, Abilities.NONE, Abilities.DROUGHT, 634, 78, 104, 78, 159, 115, 100, 45, 50, 267),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.FLYING, 28, 90.5, Abilities.SOLAR_POWER, Abilities.SOLAR_POWER, Abilities.SOLAR_POWER, 634, 118, 84, 93, 139, 110, 100, 45, 50, 267),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.FLYING, 28, 90.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 634, 98, 100, 96, 135, 110, 95, 45, 50, 267),
),
new PokemonSpecies(Species.SQUIRTLE, 1, false, false, false, "Tiny Turtle Pokémon", Type.WATER, null, 0.5, 9, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 314, 44, 48, 65, 50, 64, 43, 45, 50, 63, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.WARTORTLE, 1, false, false, false, "Turtle Pokémon", Type.WATER, null, 1, 22.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 405, 59, 63, 80, 65, 80, 58, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.BLASTOISE, 1, false, false, false, "Shellfish Pokémon", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
new PokemonForm("Normal", "", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, false, null, true),
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.WATER, null, 1.6, 101.1, Abilities.MEGA_LAUNCHER, Abilities.NONE, Abilities.MEGA_LAUNCHER, 630, 79, 103, 120, 135, 115, 78, 45, 50, 265),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.STEEL, 25, 85.5, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, 630, 119, 83, 130, 115, 115, 68, 45, 50, 265),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 25, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 630, 100, 95, 130, 105, 125, 75, 45, 50, 265),
),
new PokemonSpecies(Species.CATERPIE, 1, false, false, false, "Worm Pokémon", Type.BUG, null, 0.3, 2.9, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 45, 30, 35, 20, 20, 45, 255, 50, 39, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.METAPOD, 1, false, false, false, "Cocoon Pokémon", Type.BUG, null, 0.7, 9.9, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 50, 20, 55, 25, 25, 30, 120, 50, 72, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.BUTTERFREE, 1, false, false, false, "Butterfly Pokémon", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, GrowthRate.MEDIUM_FAST, 50, true, true,
new PokemonForm("Normal", "", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, true, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 32, Abilities.TINTED_LENS, Abilities.TINTED_LENS, Abilities.TINTED_LENS, 495, 85, 35, 80, 120, 90, 85, 45, 50, 198, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 495, 75, 50, 75, 120, 100, 75, 45, 50, 198, true),
),
new PokemonSpecies(Species.WEEDLE, 1, false, false, false, "Hairy Bug Pokémon", Type.BUG, Type.POISON, 0.3, 3.2, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 40, 35, 30, 20, 20, 50, 255, 70, 39, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.KAKUNA, 1, false, false, false, "Cocoon Pokémon", Type.BUG, Type.POISON, 0.6, 10, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 45, 25, 50, 25, 25, 35, 120, 70, 72, GrowthRate.MEDIUM_FAST, 50, false),
@ -963,7 +963,7 @@ export function initSpecies() {
new PokemonForm("Cute Cosplay", "cute-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
new PokemonForm("Smart Cosplay", "smart-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
new PokemonForm("Tough Cosplay", "tough-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, null, 21, 6, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, 530, 125, 95, 60, 90, 70, 90, 190, 50, 112), //+100 BST from Partner Form
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, null, 21, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 420, 45, 60, 65, 100, 75, 75, 190, 50, 112),
),
new PokemonSpecies(Species.RAICHU, 1, false, false, false, "Mouse Pokémon", Type.ELECTRIC, null, 0.8, 30, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 485, 60, 90, 55, 90, 80, 110, 75, 50, 243, GrowthRate.MEDIUM_FAST, 50, true),
new PokemonSpecies(Species.SANDSHREW, 1, false, false, false, "Mouse Pokémon", Type.GROUND, null, 0.6, 12, Abilities.SAND_VEIL, Abilities.NONE, Abilities.SAND_RUSH, 300, 50, 75, 85, 20, 30, 40, 255, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
@ -993,7 +993,7 @@ export function initSpecies() {
new PokemonSpecies(Species.DUGTRIO, 1, false, false, false, "Mole Pokémon", Type.GROUND, null, 0.7, 33.3, Abilities.SAND_VEIL, Abilities.ARENA_TRAP, Abilities.SAND_FORCE, 425, 35, 100, 50, 50, 70, 120, 50, 50, 149, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.MEOWTH, 1, false, false, false, "Scratch Cat Pokémon", Type.NORMAL, null, 0.4, 4.2, Abilities.PICKUP, Abilities.TECHNICIAN, Abilities.UNNERVE, 290, 40, 45, 35, 40, 40, 90, 255, 50, 58, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.NORMAL, null, 0.4, 4.2, Abilities.PICKUP, Abilities.TECHNICIAN, Abilities.UNNERVE, 290, 40, 45, 35, 40, 40, 90, 255, 50, 58, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 33, 4.2, Abilities.TECHNICIAN, Abilities.TECHNICIAN, Abilities.TECHNICIAN, 540, 115, 110, 65, 65, 70, 115, 255, 50, 58), //+100 BST from Persian
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 33, 4.2, Abilities.PICKUP, Abilities.TECHNICIAN, Abilities.UNNERVE, 390, 50, 85, 60, 70, 50, 75, 255, 50, 58),
),
new PokemonSpecies(Species.PERSIAN, 1, false, false, false, "Classy Cat Pokémon", Type.NORMAL, null, 1, 32, Abilities.LIMBER, Abilities.TECHNICIAN, Abilities.UNNERVE, 440, 65, 70, 60, 65, 65, 115, 90, 50, 154, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.PSYDUCK, 1, false, false, false, "Duck Pokémon", Type.WATER, null, 0.8, 19.6, Abilities.DAMP, Abilities.CLOUD_NINE, Abilities.SWIFT_SWIM, 320, 50, 52, 48, 65, 50, 55, 190, 50, 64, GrowthRate.MEDIUM_FAST, 50, false),
@ -1015,7 +1015,7 @@ export function initSpecies() {
new PokemonSpecies(Species.MACHOKE, 1, false, false, false, "Superpower Pokémon", Type.FIGHTING, null, 1.5, 70.5, Abilities.GUTS, Abilities.NO_GUARD, Abilities.STEADFAST, 405, 80, 100, 70, 50, 60, 45, 90, 50, 142, GrowthRate.MEDIUM_SLOW, 75, false),
new PokemonSpecies(Species.MACHAMP, 1, false, false, false, "Superpower Pokémon", Type.FIGHTING, null, 1.6, 130, Abilities.GUTS, Abilities.NO_GUARD, Abilities.STEADFAST, 505, 90, 130, 80, 65, 85, 55, 45, 50, 253, GrowthRate.MEDIUM_SLOW, 75, false, true,
new PokemonForm("Normal", "", Type.FIGHTING, null, 1.6, 130, Abilities.GUTS, Abilities.NO_GUARD, Abilities.STEADFAST, 505, 90, 130, 80, 65, 85, 55, 45, 50, 253, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIGHTING, null, 25, 130, Abilities.GUTS, Abilities.GUTS, Abilities.GUTS, 605, 115, 170, 95, 65, 95, 65, 45, 50, 253),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIGHTING, null, 25, 130, Abilities.GUTS, Abilities.NO_GUARD, Abilities.STEADFAST, 605, 113, 170, 90, 70, 95, 67, 45, 50, 253),
),
new PokemonSpecies(Species.BELLSPROUT, 1, false, false, false, "Flower Pokémon", Type.GRASS, Type.POISON, 0.7, 4, Abilities.CHLOROPHYLL, Abilities.NONE, Abilities.GLUTTONY, 300, 50, 75, 35, 70, 30, 40, 255, 70, 60, GrowthRate.MEDIUM_SLOW, 50, false),
new PokemonSpecies(Species.WEEPINBELL, 1, false, false, false, "Flycatcher Pokémon", Type.GRASS, Type.POISON, 1, 6.4, Abilities.CHLOROPHYLL, Abilities.NONE, Abilities.GLUTTONY, 390, 65, 90, 50, 85, 45, 55, 120, 70, 137, GrowthRate.MEDIUM_SLOW, 50, false),
@ -1048,7 +1048,7 @@ export function initSpecies() {
new PokemonSpecies(Species.GENGAR, 1, false, false, false, "Shadow Pokémon", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, GrowthRate.MEDIUM_SLOW, 50, false, true,
new PokemonForm("Normal", "", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, false, null, true),
new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GHOST, Type.POISON, 1.4, 40.5, Abilities.SHADOW_TAG, Abilities.NONE, Abilities.NONE, 600, 60, 65, 80, 170, 95, 130, 45, 50, 250),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GHOST, Type.POISON, 20, 40.5, Abilities.CURSED_BODY, Abilities.CURSED_BODY, Abilities.CURSED_BODY, 600, 140, 65, 70, 140, 85, 100, 45, 50, 250),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GHOST, Type.POISON, 20, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 600, 75, 95, 85, 160, 95, 90, 45, 50, 250),
),
new PokemonSpecies(Species.ONIX, 1, false, false, false, "Rock Snake Pokémon", Type.ROCK, Type.GROUND, 8.8, 210, Abilities.ROCK_HEAD, Abilities.STURDY, Abilities.WEAK_ARMOR, 385, 35, 45, 160, 30, 45, 70, 45, 50, 77, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.DROWZEE, 1, false, false, false, "Hypnosis Pokémon", Type.PSYCHIC, null, 1, 32.4, Abilities.INSOMNIA, Abilities.FOREWARN, Abilities.INNER_FOCUS, 328, 60, 48, 45, 43, 90, 42, 190, 70, 66, GrowthRate.MEDIUM_FAST, 50, false),
@ -1056,7 +1056,7 @@ export function initSpecies() {
new PokemonSpecies(Species.KRABBY, 1, false, false, false, "River Crab Pokémon", Type.WATER, null, 0.4, 6.5, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 325, 30, 105, 90, 25, 25, 50, 225, 50, 65, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.KINGLER, 1, false, false, false, "Pincer Pokémon", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 19, 60, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, 575, 90, 155, 140, 50, 80, 70, 60, 50, 166),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 19, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 575, 70, 165, 145, 60, 70, 65, 60, 50, 166),
),
new PokemonSpecies(Species.VOLTORB, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 0.5, 10.4, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 330, 40, 30, 50, 55, 55, 100, 190, 70, 66, GrowthRate.MEDIUM_FAST, null, false),
new PokemonSpecies(Species.ELECTRODE, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 1.2, 66.6, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 490, 60, 50, 70, 80, 80, 150, 60, 70, 172, GrowthRate.MEDIUM_FAST, null, false),
@ -1100,13 +1100,13 @@ export function initSpecies() {
),
new PokemonSpecies(Species.LAPRAS, 1, false, false, false, "Transport Pokémon", Type.WATER, Type.ICE, 2.5, 220, Abilities.WATER_ABSORB, Abilities.SHELL_ARMOR, Abilities.HYDRATION, 535, 130, 85, 80, 85, 95, 60, 45, 50, 187, GrowthRate.SLOW, 50, false, true,
new PokemonForm("Normal", "", Type.WATER, Type.ICE, 2.5, 220, Abilities.WATER_ABSORB, Abilities.SHELL_ARMOR, Abilities.HYDRATION, 535, 130, 85, 80, 85, 95, 60, 45, 50, 187, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.ICE, 24, 220, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, 635, 170, 85, 95, 115, 110, 60, 45, 50, 187),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.ICE, 24, 220, Abilities.WATER_ABSORB, Abilities.SHELL_ARMOR, Abilities.HYDRATION, 635, 160, 95, 110, 95, 125, 50, 45, 50, 187),
),
new PokemonSpecies(Species.DITTO, 1, false, false, false, "Transform Pokémon", Type.NORMAL, null, 0.3, 4, Abilities.LIMBER, Abilities.NONE, Abilities.IMPOSTER, 288, 48, 48, 48, 48, 48, 48, 35, 50, 101, GrowthRate.MEDIUM_FAST, null, false),
new PokemonSpecies(Species.EEVEE, 1, false, false, false, "Evolution Pokémon", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 325, 55, 55, 50, 45, 65, 55, 45, 50, 65, GrowthRate.MEDIUM_FAST, 87.5, false, true,
new PokemonForm("Normal", "", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 325, 55, 55, 50, 45, 65, 55, 45, 50, 65, false, null, true),
new PokemonForm("Partner", "partner", Type.NORMAL, null, 0.3, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 435, 65, 75, 70, 65, 85, 75, 45, 50, 65, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 18, 6.5, Abilities.PROTEAN, Abilities.PROTEAN, Abilities.PROTEAN, 535, 105, 95, 70, 95, 85, 85, 45, 50, 65), //+100 BST from Partner Form
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 18, 6.5, Abilities.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 425, 70, 75, 80, 60, 95, 45, 45, 50, 65),
),
new PokemonSpecies(Species.VAPOREON, 1, false, false, false, "Bubble Jet Pokémon", Type.WATER, null, 1, 29, Abilities.WATER_ABSORB, Abilities.NONE, Abilities.HYDRATION, 525, 130, 65, 60, 110, 95, 65, 45, 50, 184, GrowthRate.MEDIUM_FAST, 87.5, false),
new PokemonSpecies(Species.JOLTEON, 1, false, false, false, "Lightning Pokémon", Type.ELECTRIC, null, 0.8, 24.5, Abilities.VOLT_ABSORB, Abilities.NONE, Abilities.QUICK_FEET, 525, 65, 65, 60, 110, 95, 130, 45, 50, 184, GrowthRate.MEDIUM_FAST, 87.5, false),
@ -1122,7 +1122,7 @@ export function initSpecies() {
),
new PokemonSpecies(Species.SNORLAX, 1, false, false, false, "Sleeping Pokémon", Type.NORMAL, null, 2.1, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 540, 160, 110, 65, 65, 110, 30, 25, 50, 189, GrowthRate.SLOW, 87.5, false, true,
new PokemonForm("Normal", "", Type.NORMAL, null, 2.1, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 540, 160, 110, 65, 65, 110, 30, 25, 50, 189, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, Type.GRASS, 35, 460, Abilities.THICK_FAT, Abilities.THICK_FAT, Abilities.THICK_FAT, 640, 200, 135, 85, 80, 125, 15, 25, 50, 189),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 35, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 640, 200, 130, 85, 75, 130, 20, 25, 50, 189),
),
new PokemonSpecies(Species.ARTICUNO, 1, true, false, false, "Freeze Pokémon", Type.ICE, Type.FLYING, 1.7, 55.4, Abilities.PRESSURE, Abilities.NONE, Abilities.SNOW_CLOAK, 580, 90, 85, 100, 95, 125, 85, 3, 35, 290, GrowthRate.SLOW, null, false),
new PokemonSpecies(Species.ZAPDOS, 1, true, false, false, "Electric Pokémon", Type.ELECTRIC, Type.FLYING, 1.6, 52.6, Abilities.PRESSURE, Abilities.NONE, Abilities.STATIC, 580, 90, 90, 85, 125, 90, 100, 3, 35, 290, GrowthRate.SLOW, null, false),
@ -1762,7 +1762,7 @@ export function initSpecies() {
new PokemonSpecies(Species.TRUBBISH, 5, false, false, false, "Trash Bag Pokémon", Type.POISON, null, 0.6, 31, Abilities.STENCH, Abilities.STICKY_HOLD, Abilities.AFTERMATH, 329, 50, 50, 62, 40, 62, 65, 190, 50, 66, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.GARBODOR, 5, false, false, false, "Trash Heap Pokémon", Type.POISON, null, 1.9, 107.3, Abilities.STENCH, Abilities.WEAK_ARMOR, Abilities.AFTERMATH, 474, 80, 95, 82, 60, 82, 75, 60, 50, 166, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.POISON, null, 1.9, 107.3, Abilities.STENCH, Abilities.WEAK_ARMOR, Abilities.AFTERMATH, 474, 80, 95, 82, 60, 82, 75, 60, 50, 166, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.POISON, Type.STEEL, 21, 107.3, Abilities.TOXIC_DEBRIS, Abilities.TOXIC_DEBRIS, Abilities.TOXIC_DEBRIS, 574, 135, 125, 102, 57, 102, 53, 60, 50, 166),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.POISON, null, 21, 107.3, Abilities.STENCH, Abilities.WEAK_ARMOR, Abilities.AFTERMATH, 574, 100, 125, 102, 80, 102, 65, 60, 50, 166),
),
new PokemonSpecies(Species.ZORUA, 5, false, false, false, "Tricky Fox Pokémon", Type.DARK, null, 0.7, 12.5, Abilities.ILLUSION, Abilities.NONE, Abilities.NONE, 330, 40, 65, 40, 80, 40, 65, 75, 50, 66, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.ZOROARK, 5, false, false, false, "Illusion Fox Pokémon", Type.DARK, null, 1.6, 81.1, Abilities.ILLUSION, Abilities.NONE, Abilities.NONE, 510, 60, 105, 60, 120, 60, 105, 45, 50, 179, GrowthRate.MEDIUM_SLOW, 87.5, false),
@ -2236,25 +2236,25 @@ export function initSpecies() {
new PokemonSpecies(Species.MELTAN, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 0.2, 8, Abilities.MAGNET_PULL, Abilities.NONE, Abilities.NONE, 300, 46, 65, 65, 55, 35, 34, 3, 0, 150, GrowthRate.SLOW, null, false),
new PokemonSpecies(Species.MELMETAL, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, GrowthRate.SLOW, null, false, true,
new PokemonForm("Normal", "", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, null, 25, 800, Abilities.IRON_FIST, Abilities.IRON_FIST, Abilities.IRON_FIST, 700, 175, 165, 155, 85, 75, 45, 3, 0, 300),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, null, 25, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 700, 170, 165, 165, 95, 75, 30, 3, 0, 300),
),
new PokemonSpecies(Species.GROOKEY, 8, false, false, false, "Chimp Pokémon", Type.GRASS, null, 0.3, 5, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 310, 50, 65, 50, 40, 40, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.THWACKEY, 8, false, false, false, "Beat Pokémon", Type.GRASS, null, 0.7, 14, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 420, 70, 85, 70, 55, 60, 80, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.RILLABOOM, 8, false, false, false, "Drummer Pokémon", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
new PokemonForm("Normal", "", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, null, 28, 90, Abilities.GRASSY_SURGE, Abilities.GRASSY_SURGE, Abilities.GRASSY_SURGE, 630, 125, 150, 115, 65, 95, 80, 45, 50, 265),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, null, 28, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 630, 125, 150, 115, 75, 90, 75, 45, 50, 265),
),
new PokemonSpecies(Species.SCORBUNNY, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.3, 4.5, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 310, 50, 71, 40, 40, 40, 69, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.RABOOT, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.6, 9, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 420, 65, 86, 60, 55, 60, 94, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.CINDERACE, 8, false, false, false, "Striker Pokémon", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
new PokemonForm("Normal", "", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, null, 27, 33, Abilities.LIBERO, Abilities.LIBERO, Abilities.LIBERO, 630, 90, 151, 85, 85, 85, 134, 45, 50, 265),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, null, 27, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 630, 100, 145, 90, 75, 90, 130, 45, 50, 265),
),
new PokemonSpecies(Species.SOBBLE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.3, 4, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 310, 50, 40, 40, 70, 40, 70, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.DRIZZILE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.7, 11.5, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 420, 65, 60, 55, 95, 55, 90, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false),
new PokemonSpecies(Species.INTELEON, 8, false, false, false, "Secret Agent Pokémon", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true,
new PokemonForm("Normal", "", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 40, 45.2, Abilities.SNIPER, Abilities.SNIPER, Abilities.SNIPER, 630, 90, 90, 85, 150, 85, 130, 45, 50, 265),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 40, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 630, 90, 100, 90, 150, 90, 110, 45, 50, 265),
),
new PokemonSpecies(Species.SKWOVET, 8, false, false, false, "Cheeky Pokémon", Type.NORMAL, null, 0.3, 2.5, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 275, 70, 55, 55, 35, 35, 25, 255, 50, 55, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.GREEDENT, 8, false, false, false, "Greedy Pokémon", Type.NORMAL, null, 0.6, 6, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 460, 120, 95, 95, 55, 75, 20, 90, 50, 161, GrowthRate.MEDIUM_FAST, 50, false),
@ -2262,13 +2262,13 @@ export function initSpecies() {
new PokemonSpecies(Species.CORVISQUIRE, 8, false, false, false, "Raven Pokémon", Type.FLYING, null, 0.8, 16, Abilities.KEEN_EYE, Abilities.UNNERVE, Abilities.BIG_PECKS, 365, 68, 67, 55, 43, 55, 77, 120, 50, 128, GrowthRate.MEDIUM_SLOW, 50, false),
new PokemonSpecies(Species.CORVIKNIGHT, 8, false, false, false, "Raven Pokémon", Type.FLYING, Type.STEEL, 2.2, 75, Abilities.PRESSURE, Abilities.UNNERVE, Abilities.MIRROR_ARMOR, 495, 98, 87, 105, 53, 85, 67, 45, 50, 248, GrowthRate.MEDIUM_SLOW, 50, false, true,
new PokemonForm("Normal", "", Type.FLYING, Type.STEEL, 2.2, 75, Abilities.PRESSURE, Abilities.UNNERVE, Abilities.MIRROR_ARMOR, 495, 98, 87, 105, 53, 85, 67, 45, 50, 248, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FLYING, Type.STEEL, 14, 75, Abilities.MIRROR_ARMOR, Abilities.MIRROR_ARMOR, Abilities.MIRROR_ARMOR, 595, 128, 102, 140, 53, 95, 77, 45, 50, 248),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FLYING, Type.STEEL, 14, 75, Abilities.PRESSURE, Abilities.UNNERVE, Abilities.MIRROR_ARMOR, 595, 125, 100, 135, 60, 95, 80, 45, 50, 248),
),
new PokemonSpecies(Species.BLIPBUG, 8, false, false, false, "Larva Pokémon", Type.BUG, null, 0.4, 8, Abilities.SWARM, Abilities.COMPOUND_EYES, Abilities.TELEPATHY, 180, 25, 20, 20, 25, 45, 45, 255, 50, 36, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.DOTTLER, 8, false, false, false, "Radome Pokémon", Type.BUG, Type.PSYCHIC, 0.4, 19.5, Abilities.SWARM, Abilities.COMPOUND_EYES, Abilities.TELEPATHY, 335, 50, 35, 80, 50, 90, 30, 120, 50, 117, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.ORBEETLE, 8, false, false, false, "Seven Spot Pokémon", Type.BUG, Type.PSYCHIC, 0.4, 40.8, Abilities.SWARM, Abilities.FRISK, Abilities.TELEPATHY, 505, 60, 45, 110, 80, 120, 90, 45, 50, 253, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.BUG, Type.PSYCHIC, 0.4, 40.8, Abilities.SWARM, Abilities.FRISK, Abilities.TELEPATHY, 505, 60, 45, 110, 80, 120, 90, 45, 50, 253, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.PSYCHIC, 14, 40.8, Abilities.TRACE, Abilities.TRACE, Abilities.TRACE, 605, 90, 45, 130, 110, 140, 90, 45, 50, 253),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.PSYCHIC, 14, 40.8, Abilities.SWARM, Abilities.FRISK, Abilities.TELEPATHY, 605, 75, 50, 140, 90, 150, 100, 45, 50, 253),
),
new PokemonSpecies(Species.NICKIT, 8, false, false, false, "Fox Pokémon", Type.DARK, null, 0.6, 8.9, Abilities.RUN_AWAY, Abilities.UNBURDEN, Abilities.STAKEOUT, 245, 40, 28, 28, 47, 52, 50, 255, 50, 49, GrowthRate.FAST, 50, false),
new PokemonSpecies(Species.THIEVUL, 8, false, false, false, "Fox Pokémon", Type.DARK, null, 1.2, 19.9, Abilities.RUN_AWAY, Abilities.UNBURDEN, Abilities.STAKEOUT, 455, 70, 58, 58, 87, 92, 90, 127, 50, 159, GrowthRate.FAST, 50, false),
@ -2279,7 +2279,7 @@ export function initSpecies() {
new PokemonSpecies(Species.CHEWTLE, 8, false, false, false, "Snapping Pokémon", Type.WATER, null, 0.3, 8.5, Abilities.STRONG_JAW, Abilities.SHELL_ARMOR, Abilities.SWIFT_SWIM, 284, 50, 64, 50, 38, 38, 44, 255, 50, 57, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.DREDNAW, 8, false, false, false, "Bite Pokémon", Type.WATER, Type.ROCK, 1, 115.5, Abilities.STRONG_JAW, Abilities.SHELL_ARMOR, Abilities.SWIFT_SWIM, 485, 90, 115, 90, 48, 68, 74, 75, 50, 170, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.WATER, Type.ROCK, 1, 115.5, Abilities.STRONG_JAW, Abilities.SHELL_ARMOR, Abilities.SWIFT_SWIM, 485, 90, 115, 90, 48, 68, 74, 75, 50, 170, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.ROCK, 24, 115.5, Abilities.STRONG_JAW, Abilities.STRONG_JAW, Abilities.STRONG_JAW, 585, 115, 145, 115, 43, 83, 84, 75, 50, 170),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.ROCK, 24, 115.5, Abilities.STRONG_JAW, Abilities.SHELL_ARMOR, Abilities.SWIFT_SWIM, 585, 115, 150, 110, 55, 85, 70, 75, 50, 170),
),
new PokemonSpecies(Species.YAMPER, 8, false, false, false, "Puppy Pokémon", Type.ELECTRIC, null, 0.3, 13.5, Abilities.BALL_FETCH, Abilities.NONE, Abilities.RATTLED, 270, 59, 45, 50, 40, 50, 26, 255, 50, 54, GrowthRate.FAST, 50, false),
new PokemonSpecies(Species.BOLTUND, 8, false, false, false, "Dog Pokémon", Type.ELECTRIC, null, 1, 34, Abilities.STRONG_JAW, Abilities.NONE, Abilities.COMPETITIVE, 490, 69, 90, 60, 90, 60, 121, 45, 50, 172, GrowthRate.FAST, 50, false),
@ -2287,21 +2287,21 @@ export function initSpecies() {
new PokemonSpecies(Species.CARKOL, 8, false, false, false, "Coal Pokémon", Type.ROCK, Type.FIRE, 1.1, 78, Abilities.STEAM_ENGINE, Abilities.FLAME_BODY, Abilities.FLASH_FIRE, 410, 80, 60, 90, 60, 70, 50, 120, 50, 144, GrowthRate.MEDIUM_SLOW, 50, false),
new PokemonSpecies(Species.COALOSSAL, 8, false, false, false, "Coal Pokémon", Type.ROCK, Type.FIRE, 2.8, 310.5, Abilities.STEAM_ENGINE, Abilities.FLAME_BODY, Abilities.FLASH_FIRE, 510, 110, 80, 120, 80, 90, 30, 45, 50, 255, GrowthRate.MEDIUM_SLOW, 50, false, true,
new PokemonForm("Normal", "", Type.ROCK, Type.FIRE, 2.8, 310.5, Abilities.STEAM_ENGINE, Abilities.FLAME_BODY, Abilities.FLASH_FIRE, 510, 110, 80, 120, 80, 90, 30, 45, 50, 255, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ROCK, Type.FIRE, 42, 310.5, Abilities.STEAM_ENGINE, Abilities.STEAM_ENGINE, Abilities.STEAM_ENGINE, 610, 140, 95, 130, 95, 110, 40, 45, 50, 255),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ROCK, Type.FIRE, 42, 310.5, Abilities.STEAM_ENGINE, Abilities.FLAME_BODY, Abilities.FLASH_FIRE, 610, 140, 95, 150, 95, 105, 25, 45, 50, 255),
),
new PokemonSpecies(Species.APPLIN, 8, false, false, false, "Apple Core Pokémon", Type.GRASS, Type.DRAGON, 0.2, 0.5, Abilities.RIPEN, Abilities.GLUTTONY, Abilities.BULLETPROOF, 260, 40, 40, 80, 40, 40, 20, 255, 50, 52, GrowthRate.ERRATIC, 50, false),
new PokemonSpecies(Species.FLAPPLE, 8, false, false, false, "Apple Wing Pokémon", Type.GRASS, Type.DRAGON, 0.3, 1, Abilities.RIPEN, Abilities.GLUTTONY, Abilities.HUSTLE, 485, 70, 110, 80, 95, 60, 70, 45, 50, 170, GrowthRate.ERRATIC, 50, false, true,
new PokemonForm("Normal", "", Type.GRASS, Type.DRAGON, 0.3, 1, Abilities.RIPEN, Abilities.GLUTTONY, Abilities.HUSTLE, 485, 70, 110, 80, 95, 60, 70, 45, 50, 170, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.DRAGON, 24, 1, Abilities.HUSTLE, Abilities.HUSTLE, Abilities.HUSTLE, 585, 90, 130, 100, 85, 80, 100, 45, 50, 170),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.DRAGON, 24, 1, Abilities.RIPEN, Abilities.GLUTTONY, Abilities.HUSTLE, 585, 90, 140, 90, 120, 75, 70, 45, 50, 170),
),
new PokemonSpecies(Species.APPLETUN, 8, false, false, false, "Apple Nectar Pokémon", Type.GRASS, Type.DRAGON, 0.4, 13, Abilities.RIPEN, Abilities.GLUTTONY, Abilities.THICK_FAT, 485, 110, 85, 80, 100, 80, 30, 45, 50, 170, GrowthRate.ERRATIC, 50, false, true,
new PokemonForm("Normal", "", Type.GRASS, Type.DRAGON, 0.4, 13, Abilities.RIPEN, Abilities.GLUTTONY, Abilities.THICK_FAT, 485, 110, 85, 80, 100, 80, 30, 45, 50, 170, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.DRAGON, 24, 13, Abilities.THICK_FAT, Abilities.THICK_FAT, Abilities.THICK_FAT, 585, 130, 75, 115, 125, 115, 25, 45, 50, 170),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.DRAGON, 24, 13, Abilities.RIPEN, Abilities.GLUTTONY, Abilities.THICK_FAT, 585, 140, 95, 95, 135, 95, 25, 45, 50, 170),
),
new PokemonSpecies(Species.SILICOBRA, 8, false, false, false, "Sand Snake Pokémon", Type.GROUND, null, 2.2, 7.6, Abilities.SAND_SPIT, Abilities.SHED_SKIN, Abilities.SAND_VEIL, 315, 52, 57, 75, 35, 50, 46, 255, 50, 63, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.SANDACONDA, 8, false, false, false, "Sand Snake Pokémon", Type.GROUND, null, 3.8, 65.5, Abilities.SAND_SPIT, Abilities.SHED_SKIN, Abilities.SAND_VEIL, 510, 72, 107, 125, 65, 70, 71, 120, 50, 179, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.GROUND, null, 3.8, 65.5, Abilities.SAND_SPIT, Abilities.SHED_SKIN, Abilities.SAND_VEIL, 510, 72, 107, 125, 65, 70, 71, 120, 50, 179, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GROUND, null, 22, 65.5, Abilities.SAND_SPIT, Abilities.SAND_SPIT, Abilities.SAND_SPIT, 610, 117, 137, 140, 55, 80, 81, 120, 50, 179),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GROUND, null, 22, 65.5, Abilities.SAND_SPIT, Abilities.SHED_SKIN, Abilities.SAND_VEIL, 610, 90, 135, 150, 75, 80, 80, 120, 50, 179),
),
new PokemonSpecies(Species.CRAMORANT, 8, false, false, false, "Gulp Pokémon", Type.FLYING, Type.WATER, 0.8, 18, Abilities.GULP_MISSILE, Abilities.NONE, Abilities.NONE, 475, 70, 85, 55, 85, 95, 85, 45, 50, 166, GrowthRate.MEDIUM_FAST, 50, false, false,
new PokemonForm("Normal", "", Type.FLYING, Type.WATER, 0.8, 18, Abilities.GULP_MISSILE, Abilities.NONE, Abilities.NONE, 475, 70, 85, 55, 85, 95, 85, 45, 50, 166, false, null, true),
@ -2314,12 +2314,12 @@ export function initSpecies() {
new PokemonSpecies(Species.TOXTRICITY, 8, false, false, false, "Punk Pokémon", Type.ELECTRIC, Type.POISON, 1.6, 40, Abilities.PUNK_ROCK, Abilities.PLUS, Abilities.TECHNICIAN, 502, 75, 98, 70, 114, 70, 75, 45, 50, 176, GrowthRate.MEDIUM_SLOW, 50, false, true,
new PokemonForm("Amped Form", "amped", Type.ELECTRIC, Type.POISON, 1.6, 40, Abilities.PUNK_ROCK, Abilities.PLUS, Abilities.TECHNICIAN, 502, 75, 98, 70, 114, 70, 75, 45, 50, 176, false, "", true),
new PokemonForm("Low-Key Form", "lowkey", Type.ELECTRIC, Type.POISON, 1.6, 40, Abilities.PUNK_ROCK, Abilities.MINUS, Abilities.TECHNICIAN, 502, 75, 98, 70, 114, 70, 75, 45, 50, 176, false, "lowkey", true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, Type.POISON, 24, 40, Abilities.PUNK_ROCK, Abilities.PUNK_ROCK, Abilities.PUNK_ROCK, 602, 114, 98, 82, 144, 82, 82, 45, 50, 176),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, Type.POISON, 24, 40, Abilities.PUNK_ROCK, Abilities.MINUS, Abilities.TECHNICIAN, 602, 95, 118, 80, 144, 80, 85, 45, 50, 176),
),
new PokemonSpecies(Species.SIZZLIPEDE, 8, false, false, false, "Radiator Pokémon", Type.FIRE, Type.BUG, 0.7, 1, Abilities.FLASH_FIRE, Abilities.WHITE_SMOKE, Abilities.FLAME_BODY, 305, 50, 65, 45, 50, 50, 45, 190, 50, 61, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.CENTISKORCH, 8, false, false, false, "Radiator Pokémon", Type.FIRE, Type.BUG, 3, 120, Abilities.FLASH_FIRE, Abilities.WHITE_SMOKE, Abilities.FLAME_BODY, 525, 100, 115, 65, 90, 90, 65, 75, 50, 184, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.FIRE, Type.BUG, 3, 120, Abilities.FLASH_FIRE, Abilities.WHITE_SMOKE, Abilities.FLAME_BODY, 525, 100, 115, 65, 90, 90, 65, 75, 50, 184, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.BUG, 75, 120, Abilities.FLASH_FIRE, Abilities.FLASH_FIRE, Abilities.FLASH_FIRE, 625, 140, 145, 75, 90, 100, 75, 75, 50, 184),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.BUG, 75, 120, Abilities.FLASH_FIRE, Abilities.WHITE_SMOKE, Abilities.FLAME_BODY, 625, 125, 145, 75, 105, 105, 70, 75, 50, 184),
),
new PokemonSpecies(Species.CLOBBOPUS, 8, false, false, false, "Tantrum Pokémon", Type.FIGHTING, null, 0.6, 4, Abilities.LIMBER, Abilities.NONE, Abilities.TECHNICIAN, 310, 50, 68, 60, 50, 50, 32, 180, 50, 62, GrowthRate.MEDIUM_SLOW, 50, false),
new PokemonSpecies(Species.GRAPPLOCT, 8, false, false, false, "Jujitsu Pokémon", Type.FIGHTING, null, 1.6, 39, Abilities.LIMBER, Abilities.NONE, Abilities.TECHNICIAN, 480, 80, 118, 90, 70, 80, 42, 45, 50, 168, GrowthRate.MEDIUM_SLOW, 50, false),
@ -2335,13 +2335,13 @@ export function initSpecies() {
new PokemonSpecies(Species.HATTREM, 8, false, false, false, "Serene Pokémon", Type.PSYCHIC, null, 0.6, 4.8, Abilities.HEALER, Abilities.ANTICIPATION, Abilities.MAGIC_BOUNCE, 370, 57, 40, 65, 86, 73, 49, 120, 50, 130, GrowthRate.SLOW, 0, false),
new PokemonSpecies(Species.HATTERENE, 8, false, false, false, "Silent Pokémon", Type.PSYCHIC, Type.FAIRY, 2.1, 5.1, Abilities.HEALER, Abilities.ANTICIPATION, Abilities.MAGIC_BOUNCE, 510, 57, 90, 95, 136, 103, 29, 45, 50, 255, GrowthRate.SLOW, 0, false, true,
new PokemonForm("Normal", "", Type.PSYCHIC, Type.FAIRY, 2.1, 5.1, Abilities.HEALER, Abilities.ANTICIPATION, Abilities.MAGIC_BOUNCE, 510, 57, 90, 95, 136, 103, 29, 45, 50, 255, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.PSYCHIC, Type.FAIRY, 26, 5.1, Abilities.MAGIC_BOUNCE, Abilities.MAGIC_BOUNCE, Abilities.MAGIC_BOUNCE, 610, 97, 90, 105, 146, 122, 50, 45, 50, 255),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.PSYCHIC, Type.FAIRY, 26, 5.1, Abilities.HEALER, Abilities.ANTICIPATION, Abilities.MAGIC_BOUNCE, 610, 70, 105, 110, 160, 125, 40, 45, 50, 255),
),
new PokemonSpecies(Species.IMPIDIMP, 8, false, false, false, "Wily Pokémon", Type.DARK, Type.FAIRY, 0.4, 5.5, Abilities.PRANKSTER, Abilities.FRISK, Abilities.PICKPOCKET, 265, 45, 45, 30, 55, 40, 50, 255, 50, 53, GrowthRate.MEDIUM_FAST, 100, false),
new PokemonSpecies(Species.MORGREM, 8, false, false, false, "Devious Pokémon", Type.DARK, Type.FAIRY, 0.8, 12.5, Abilities.PRANKSTER, Abilities.FRISK, Abilities.PICKPOCKET, 370, 65, 60, 45, 75, 55, 70, 120, 50, 130, GrowthRate.MEDIUM_FAST, 100, false),
new PokemonSpecies(Species.GRIMMSNARL, 8, false, false, false, "Bulk Up Pokémon", Type.DARK, Type.FAIRY, 1.5, 61, Abilities.PRANKSTER, Abilities.FRISK, Abilities.PICKPOCKET, 510, 95, 120, 65, 95, 75, 60, 45, 50, 255, GrowthRate.MEDIUM_FAST, 100, false, true,
new PokemonForm("Normal", "", Type.DARK, Type.FAIRY, 1.5, 61, Abilities.PRANKSTER, Abilities.FRISK, Abilities.PICKPOCKET, 510, 95, 120, 65, 95, 75, 60, 45, 50, 255, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.DARK, Type.FAIRY, 32, 61, Abilities.PRANKSTER, Abilities.PRANKSTER, Abilities.PRANKSTER, 610, 135, 138, 77, 110, 85, 65, 45, 50, 255),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.DARK, Type.FAIRY, 32, 61, Abilities.PRANKSTER, Abilities.FRISK, Abilities.PICKPOCKET, 610, 120, 155, 75, 110, 85, 65, 45, 50, 255),
),
new PokemonSpecies(Species.OBSTAGOON, 8, false, false, false, "Blocking Pokémon", Type.DARK, Type.NORMAL, 1.6, 46, Abilities.RECKLESS, Abilities.GUTS, Abilities.DEFIANT, 520, 93, 90, 101, 60, 81, 95, 45, 50, 260, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.PERRSERKER, 8, false, false, false, "Viking Pokémon", Type.STEEL, null, 0.8, 28, Abilities.BATTLE_ARMOR, Abilities.TOUGH_CLAWS, Abilities.STEELY_SPIRIT, 440, 70, 110, 100, 50, 60, 50, 90, 50, 154, GrowthRate.MEDIUM_FAST, 50, false),
@ -2360,7 +2360,7 @@ export function initSpecies() {
new PokemonForm("Ruby Swirl", "ruby-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
new PokemonForm("Caramel Swirl", "caramel-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
new PokemonForm("Rainbow Swirl", "rainbow-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FAIRY, null, 30, 0.5, Abilities.MISTY_SURGE, Abilities.MISTY_SURGE, Abilities.MISTY_SURGE, 595, 135, 60, 75, 130, 131, 64, 100, 50, 173),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FAIRY, null, 30, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 595, 85, 70, 85, 140, 150, 65, 100, 50, 173),
),
new PokemonSpecies(Species.FALINKS, 8, false, false, false, "Formation Pokémon", Type.FIGHTING, null, 3, 62, Abilities.BATTLE_ARMOR, Abilities.NONE, Abilities.DEFIANT, 470, 65, 100, 100, 70, 60, 75, 45, 50, 165, GrowthRate.MEDIUM_FAST, null, false),
new PokemonSpecies(Species.PINCURCHIN, 8, false, false, false, "Sea Urchin Pokémon", Type.ELECTRIC, null, 0.3, 1, Abilities.LIGHTNING_ROD, Abilities.NONE, Abilities.ELECTRIC_SURGE, 435, 48, 101, 95, 91, 85, 15, 75, 50, 152, GrowthRate.MEDIUM_FAST, 50, false),
@ -2382,7 +2382,7 @@ export function initSpecies() {
new PokemonSpecies(Species.CUFANT, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 1.2, 100, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 330, 72, 80, 49, 40, 49, 40, 190, 50, 66, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.COPPERAJAH, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, Type.GROUND, 23, 650, Abilities.MOLD_BREAKER, Abilities.MOLD_BREAKER, Abilities.MOLD_BREAKER, 600, 167, 155, 89, 80, 89, 20, 90, 50, 175),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, null, 23, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 600, 150, 160, 80, 90, 80, 40, 90, 50, 175),
),
new PokemonSpecies(Species.DRACOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.DRAGON, 1.8, 190, Abilities.VOLT_ABSORB, Abilities.HUSTLE, Abilities.SAND_RUSH, 505, 90, 100, 90, 80, 70, 75, 45, 50, 177, GrowthRate.SLOW, null, false),
new PokemonSpecies(Species.ARCTOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.ICE, 2.3, 150, Abilities.VOLT_ABSORB, Abilities.STATIC, Abilities.SLUSH_RUSH, 505, 90, 100, 90, 90, 80, 55, 45, 50, 177, GrowthRate.SLOW, null, false),
@ -2390,7 +2390,7 @@ export function initSpecies() {
new PokemonSpecies(Species.ARCTOVISH, 8, false, false, false, "Fossil Pokémon", Type.WATER, Type.ICE, 2, 175, Abilities.WATER_ABSORB, Abilities.ICE_BODY, Abilities.SLUSH_RUSH, 505, 90, 90, 100, 80, 90, 55, 45, 50, 177, GrowthRate.SLOW, null, false),
new PokemonSpecies(Species.DURALUDON, 8, false, false, false, "Alloy Pokémon", Type.STEEL, Type.DRAGON, 1.8, 40, Abilities.LIGHT_METAL, Abilities.HEAVY_METAL, Abilities.STALWART, 535, 70, 95, 115, 120, 50, 85, 45, 50, 187, GrowthRate.MEDIUM_FAST, 50, false, true,
new PokemonForm("Normal", "", Type.STEEL, Type.DRAGON, 1.8, 40, Abilities.LIGHT_METAL, Abilities.HEAVY_METAL, Abilities.STALWART, 535, 70, 95, 115, 120, 50, 85, 45, 50, 187, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, Type.DRAGON, 43, 40, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, 635, 100, 105, 119, 166, 57, 88, 45, 50, 187),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, Type.DRAGON, 43, 40, Abilities.LIGHT_METAL, Abilities.HEAVY_METAL, Abilities.STALWART, 635, 90, 110, 145, 140, 60, 90, 45, 50, 187),
),
new PokemonSpecies(Species.DREEPY, 8, false, false, false, "Lingering Pokémon", Type.DRAGON, Type.GHOST, 0.5, 2, Abilities.CLEAR_BODY, Abilities.INFILTRATOR, Abilities.CURSED_BODY, 270, 28, 60, 30, 40, 30, 82, 45, 50, 54, GrowthRate.SLOW, 50, false),
new PokemonSpecies(Species.DRAKLOAK, 8, false, false, false, "Caretaker Pokémon", Type.DRAGON, Type.GHOST, 1.4, 11, Abilities.CLEAR_BODY, Abilities.INFILTRATOR, Abilities.CURSED_BODY, 410, 68, 80, 50, 60, 50, 102, 45, 50, 144, GrowthRate.SLOW, 50, false),
@ -2411,8 +2411,8 @@ export function initSpecies() {
new PokemonSpecies(Species.URSHIFU, 8, true, false, false, "Wushu Pokémon", Type.FIGHTING, Type.DARK, 1.9, 105, Abilities.UNSEEN_FIST, Abilities.NONE, Abilities.NONE, 550, 100, 130, 100, 63, 60, 97, 3, 50, 275, GrowthRate.SLOW, 87.5, false, true,
new PokemonForm("Single Strike Style", "single-strike", Type.FIGHTING, Type.DARK, 1.9, 105, Abilities.UNSEEN_FIST, Abilities.NONE, Abilities.NONE, 550, 100, 130, 100, 63, 60, 97, 3, 50, 275, false, "", true),
new PokemonForm("Rapid Strike Style", "rapid-strike", Type.FIGHTING, Type.WATER, 1.9, 105, Abilities.UNSEEN_FIST, Abilities.NONE, Abilities.NONE, 550, 100, 130, 100, 63, 60, 97, 3, 50, 275, false, null, true),
new PokemonForm("G-Max Single Strike Style", SpeciesFormKey.GIGANTAMAX_SINGLE, Type.FIGHTING, Type.DARK, 29, 105, Abilities.UNSEEN_FIST, Abilities.NONE, Abilities.NONE, 650, 125, 150, 115, 73, 70, 117, 3, 50, 275),
new PokemonForm("G-Max Rapid Strike Style", SpeciesFormKey.GIGANTAMAX_RAPID, Type.FIGHTING, Type.WATER, 26, 105, Abilities.UNSEEN_FIST, Abilities.NONE, Abilities.NONE, 650, 125, 150, 115, 73, 70, 117, 3, 50, 275),
new PokemonForm("G-Max Single Strike Style", SpeciesFormKey.GIGANTAMAX_SINGLE, Type.FIGHTING, Type.DARK, 29, 105, Abilities.UNSEEN_FIST, Abilities.NONE, Abilities.NONE, 650, 125, 160, 120, 75, 70, 100, 3, 50, 275),
new PokemonForm("G-Max Rapid Strike Style", SpeciesFormKey.GIGANTAMAX_RAPID, Type.FIGHTING, Type.WATER, 26, 105, Abilities.UNSEEN_FIST, Abilities.NONE, Abilities.NONE, 650, 125, 160, 120, 75, 70, 100, 3, 50, 275),
),
new PokemonSpecies(Species.ZARUDE, 8, false, false, true, "Rogue Monkey Pokémon", Type.DARK, Type.GRASS, 1.8, 70, Abilities.LEAF_GUARD, Abilities.NONE, Abilities.NONE, 600, 105, 120, 105, 70, 95, 105, 3, 0, 300, GrowthRate.SLOW, null, false, false,
new PokemonForm("Normal", "", Type.DARK, Type.GRASS, 1.8, 70, Abilities.LEAF_GUARD, Abilities.NONE, Abilities.NONE, 600, 105, 120, 105, 70, 95, 105, 3, 0, 300, false, null, true),
@ -3622,7 +3622,7 @@ export const starterPassiveAbilities = {
[Species.YAMASK]: Abilities.PURIFYING_SALT,
[Species.TIRTOUGA]: Abilities.WATER_ABSORB,
[Species.ARCHEN]: Abilities.MULTISCALE,
[Species.TRUBBISH]: Abilities.NEUTRALIZING_GAS,
[Species.TRUBBISH]: Abilities.TOXIC_DEBRIS,
[Species.ZORUA]: Abilities.DARK_AURA,
[Species.MINCCINO]: Abilities.FUR_COAT,
[Species.GOTHITA]: Abilities.UNNERVE,
@ -3783,7 +3783,7 @@ export const starterPassiveAbilities = {
[Species.SINISTEA]: Abilities.SHADOW_SHIELD,
[Species.HATENNA]: Abilities.FAIRY_AURA,
[Species.IMPIDIMP]: Abilities.FUR_COAT,
[Species.MILCERY]: Abilities.REGENERATOR,
[Species.MILCERY]: Abilities.MISTY_SURGE,
[Species.FALINKS]: Abilities.PARENTAL_BOND,
[Species.PINCURCHIN]: Abilities.ELECTROMORPHOSIS,
[Species.SNOM]: Abilities.SNOW_WARNING,

View File

@ -3,7 +3,7 @@ import BattleScene, { AnySound } from "../battle-scene";
import { Variant, VariantSet, variantColorCache } from "#app/data/variant";
import { variantData } from "#app/data/variant";
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr } from "../data/move";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, StatusMoveTypeImmunityAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, NeutralDamageAgainstFlyingTypeMultiplierAttr, OneHitKOAccuracyAttr } from "../data/move";
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species";
import { Constructor } from "#app/utils";
import * as Utils from "../utils";
@ -22,7 +22,7 @@ import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoo
import { WeatherType } from "../data/weather";
import { TempBattleStat } from "../data/temp-battle-stat";
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "../data/arena-tag";
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr, IgnoreOpponentEvasionAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr } from "../data/ability";
import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldBattleStatMultiplierAbAttrs, FieldMultiplyBattleStatAbAttr, AddSecondStrikeAbAttr, IgnoreOpponentEvasionAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr } from "../data/ability";
import PokemonData from "../system/pokemon-data";
import { BattlerIndex } from "../battle";
import { Mode } from "../ui/ui";
@ -1207,84 +1207,61 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN) && !this.getTag(SemiInvulnerableTag));
}
/**
* Calculates the type of a move when used by this Pokemon after
* type-changing move and ability attributes have applied.
* @param move {@linkcode Move} The move being used.
* @param simulated If `true`, prevents showing abilities applied in this calculation.
* @returns the {@linkcode Type} of the move after attributes are applied
*/
getMoveType(move: Move, simulated: boolean = true): Type {
const moveTypeHolder = new Utils.NumberHolder(move.type);
applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder);
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder);
return moveTypeHolder.value as Type;
}
/**
* Calculates the effectiveness of a move against the Pokémon.
*
* @param source {@linkcode Pokemon} The attacking Pokémon.
* @param move {@linkcode Move} The move being used by the attacking Pokémon.
* @param ignoreAbility Whether to ignore abilities that might affect type effectiveness or immunity (defaults to `false`).
* @param simulated Whether to apply abilities via simulated calls (defaults to `true`)
* @param cancelled {@linkcode Utils.BooleanHolder} Stores whether the move was cancelled by a non-type-based immunity.
* Currently only used by {@linkcode Pokemon.apply} to determine whether a "No effect" message should be shown.
* @returns The type damage multiplier, indicating the effectiveness of the move
* @param source - The Pokémon using the move.
* @param move - The move being used.
* @returns The type damage multiplier or 1 if it's a status move
*/
getMoveEffectiveness(source: Pokemon, move: Move, ignoreAbility: boolean = false, simulated: boolean = true, cancelled?: Utils.BooleanHolder): TypeDamageMultiplier {
if (move.hasAttr(TypelessAttr)) {
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier {
if (move.getMove().category === MoveCategory.STATUS) {
return 1;
}
const moveType = source.getMoveType(move);
const typeMultiplier = new Utils.NumberHolder((move.category !== MoveCategory.STATUS || move.hasAttr(RespectAttackTypeImmunityAttr))
? this.getAttackTypeEffectiveness(moveType, source, false, simulated)
: 1);
return this.getAttackMoveEffectiveness(source, move, !this.battleData?.abilityRevealed);
}
/**
* Calculates the effectiveness of an attack move against the Pokémon.
*
* @param source - The attacking Pokémon.
* @param pokemonMove - The move being used by the attacking Pokémon.
* @param ignoreAbility - Whether to check for abilities that might affect type effectiveness or immunity.
* @returns The type damage multiplier, indicating the effectiveness of the move
*/
getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove, ignoreAbility: boolean = false): TypeDamageMultiplier {
const move = pokemonMove.getMove();
const typeless = move.hasAttr(TypelessAttr);
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move, source));
const cancelled = new Utils.BooleanHolder(false);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
if (this.getTypes().find(t => move.isTypeImmune(source, this, t))) {
typeMultiplier.value = 0;
if (!typeless && !ignoreAbility) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier);
}
if (!cancelled.value && !ignoreAbility) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier);
}
const cancelledHolder = cancelled ?? new Utils.BooleanHolder(false);
if (!ignoreAbility) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelledHolder, simulated, typeMultiplier);
if (!cancelledHolder.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelledHolder, simulated, typeMultiplier);
}
if (!cancelledHolder.value) {
const defendingSidePlayField = this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField();
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelledHolder));
}
}
const immuneTags = this.findTags(tag => tag instanceof TypeImmuneTag && tag.immuneType === moveType);
for (const tag of immuneTags) {
if (move && !move.getAttrs(HitsTagAttr).some(attr => attr.tagType === tag.tagType)) {
typeMultiplier.value = 0;
break;
}
}
return (!cancelledHolder.value ? typeMultiplier.value : 0) as TypeDamageMultiplier;
return (!cancelled.value ? Number(typeMultiplier.value) : 0) as TypeDamageMultiplier;
}
/**
* Calculates the type effectiveness multiplier for an attack type
* @param moveType {@linkcode Type} the type of the move being used
* @param source {@linkcode Pokemon} the Pokemon using the move
* @param moveOrType The move being used, or a type if the move is unknown
* @param source the Pokemon using the move
* @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks)
* @param simulated tag to only apply the strong winds effect message when the move is used
* @returns a multiplier for the type effectiveness
*/
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier {
getAttackTypeEffectiveness(moveOrType: Move | Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier {
const move = (moveOrType instanceof Move)
? moveOrType
: undefined;
const moveType = (moveOrType instanceof Move)
? move!.type // TODO: is this bang correct?
: moveOrType;
if (moveType === Type.STELLAR) {
return this.isTerastallized() ? 2 : 1;
}
@ -1304,7 +1281,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (source) {
const ignoreImmunity = new Utils.BooleanHolder(false);
if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) {
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType);
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, false, moveType, defType);
}
if (ignoreImmunity.value) {
return 1;
@ -1326,6 +1303,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.scene.queueMessage(i18next.t("weather:strongWindsEffectMessage"));
}
}
const immuneTags = this.findTags(tag => tag instanceof TypeImmuneTag && tag.immuneType === moveType);
for (const tag of immuneTags) {
if (move && !move.getAttrs(HitsTagAttr).some(attr => attr.tagType === tag.tagType)) {
multiplier = 0;
break;
}
}
return multiplier as TypeDamageMultiplier;
}
@ -1973,23 +1959,29 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let result: HitResult;
const damage = new Utils.NumberHolder(0);
const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
const defendingSidePlayField = this.isPlayer() ? this.scene.getPlayerField() : this.scene.getEnemyField();
const variableCategory = new Utils.NumberHolder(move.category);
const variableCategory = new Utils.IntegerHolder(move.category);
applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory);
const moveCategory = variableCategory.value as MoveCategory;
/** The move's type after type-changing effects are applied */
const moveType = source.getMoveType(move);
applyMoveAttrs(VariableMoveTypeAttr, source, this, move);
const types = this.getTypes(true, true);
/** If `value` is `true`, cancels the move and suppresses "No Effect" messages */
const cancelled = new Utils.BooleanHolder(false);
const power = move.calculateBattlePower(source, this);
const typeless = move.hasAttr(TypelessAttr);
/**
* The effectiveness of the move being used. Along with type matchups, this
* accounts for changes in effectiveness from the move's attributes and the
* abilities of both the source and this Pokemon.
*/
const typeMultiplier = this.getMoveEffectiveness(source, move, false, false, cancelled);
const typeMultiplier = new Utils.NumberHolder(!typeless && (moveCategory !== MoveCategory.STATUS || move.getAttrs(StatusMoveTypeImmunityAttr).find(attr => types.includes(attr.immuneType)))
? this.getAttackTypeEffectiveness(move, source, false, false)
: 1);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
if (typeless) {
typeMultiplier.value = 1;
}
if (types.find(t => move.isTypeImmune(source, this, t))) {
typeMultiplier.value = 0;
}
switch (moveCategory) {
case MoveCategory.PHYSICAL:
@ -1997,44 +1989,27 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const isPhysical = moveCategory === MoveCategory.PHYSICAL;
const sourceTeraType = source.getTeraType();
const power = move.calculateBattlePower(source, this);
if (!typeless) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier);
applyMoveAttrs(NeutralDamageAgainstFlyingTypeMultiplierAttr, source, this, move, typeMultiplier);
}
if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, false, typeMultiplier));
}
if (cancelled.value) {
// Cancelled moves fail silently
source.stopMultiHit(this);
return HitResult.NO_EFFECT;
result = HitResult.NO_EFFECT;
} else {
const typeBoost = source.findTag(t => t instanceof TypeBoostTag && t.boostedType === moveType) as TypeBoostTag;
const typeBoost = source.findTag(t => t instanceof TypeBoostTag && t.boostedType === move.type) as TypeBoostTag;
if (typeBoost?.oneUse) {
source.removeTag(typeBoost.tagType);
}
/** Combined damage multiplier from field effects such as weather, terrain, etc. */
const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(moveType, source.isGrounded()));
const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(move.type, source.isGrounded()));
applyMoveAttrs(IgnoreWeatherTypeDebuffAttr, source, this, move, arenaAttackTypeMultiplier);
/**
* Whether or not this Pokemon is immune to the incoming move.
* Note that this isn't fully resolved in `getMoveEffectiveness` because
* of possible type-suppressing field effects (e.g. Desolate Land's effect on Water-type attacks).
*/
const isTypeImmune = (typeMultiplier * arenaAttackTypeMultiplier.value) === 0;
if (isTypeImmune) {
// Moves with no effect that were not cancelled queue a "no effect" message before failing
source.stopMultiHit(this);
result = (move.id === Moves.SHEER_COLD)
? HitResult.IMMUNE
: HitResult.NO_EFFECT;
if (result === HitResult.IMMUNE) {
this.scene.queueMessage(i18next.t("battle:hitResultImmune", { pokemonName: this.name }));
} else {
this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) }));
}
return result;
}
const glaiveRushModifier = new Utils.IntegerHolder(1);
if (this.getTag(BattlerTagType.RECEIVE_DOUBLE_DAMAGE)) {
glaiveRushModifier.value = 2;
@ -2084,12 +2059,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (!isCritical) {
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, move.category, this.scene.currentBattle.double, screenMultiplier);
}
const isTypeImmune = (typeMultiplier.value * arenaAttackTypeMultiplier.value) === 0;
const sourceTypes = source.getTypes();
const matchesSourceType = sourceTypes[0] === moveType || (sourceTypes.length > 1 && sourceTypes[1] === moveType);
const matchesSourceType = sourceTypes[0] === move.type || (sourceTypes.length > 1 && sourceTypes[1] === move.type);
const stabMultiplier = new Utils.NumberHolder(1);
if (sourceTeraType === Type.UNKNOWN && matchesSourceType) {
stabMultiplier.value += 0.5;
} else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === moveType) {
} else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === move.type) {
stabMultiplier.value += 0.5;
}
@ -2099,9 +2075,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
stabMultiplier.value = Math.min(stabMultiplier.value + 0.5, 2.25);
}
// 25% damage debuff on moves hitting more than one non-fainted target (regardless of immunities)
const { targets, multiple } = getMoveTargets(source, move.id);
const targetMultiplier = (multiple && targets.length > 1) ? 0.75 : 1;
const targetCount = getMoveTargets(source, move.id).targets.length;
const targetMultiplier = targetCount > 1 ? 0.75 : 1; // 25% damage debuff on multi-target hits (even if it's immune)
applyMoveAttrs(VariableAtkAttr, source, this, move, sourceAtk);
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
@ -2119,7 +2094,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const randomMultiplier = ((this.scene.randBattleSeedInt(16) + 85) / 100);
damage.value = Utils.toDmgValue((((levelMultiplier * power * sourceAtk.value / targetDef.value) / 50) + 2)
* stabMultiplier.value
* typeMultiplier
* typeMultiplier.value
* arenaAttackTypeMultiplier.value
* screenMultiplier.value
* twoStrikeMultiplier.value
@ -2153,7 +2128,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
});
}
if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && moveType === Type.DRAGON) {
if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && move.type === Type.DRAGON) {
damage.value = Utils.toDmgValue(damage.value / 2);
}
@ -2167,18 +2142,22 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
result = result!; // telling TS compiler that result is defined!
if (!result) {
const isOneHitKo = new Utils.BooleanHolder(false);
applyMoveAttrs(OneHitKOAttr, source, this, move, isOneHitKo);
if (isOneHitKo.value) {
result = HitResult.ONE_HIT_KO;
isCritical = false;
damage.value = this.hp;
} else if (typeMultiplier >= 2) {
result = HitResult.SUPER_EFFECTIVE;
} else if (typeMultiplier >= 1) {
result = HitResult.EFFECTIVE;
if (!typeMultiplier.value) {
result = move.id === Moves.SHEER_COLD ? HitResult.IMMUNE : HitResult.NO_EFFECT;
} else {
result = HitResult.NOT_VERY_EFFECTIVE;
const isOneHitKo = new Utils.BooleanHolder(false);
applyMoveAttrs(OneHitKOAttr, source, this, move, isOneHitKo);
if (isOneHitKo.value) {
result = HitResult.ONE_HIT_KO;
isCritical = false;
damage.value = this.hp;
} else if (typeMultiplier.value >= 2) {
result = HitResult.SUPER_EFFECTIVE;
} else if (typeMultiplier.value >= 1) {
result = HitResult.EFFECTIVE;
} else {
result = HitResult.NOT_VERY_EFFECTIVE;
}
}
}
@ -2245,12 +2224,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
case HitResult.NOT_VERY_EFFECTIVE:
this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective"));
break;
case HitResult.ONE_HIT_KO:
this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO"));
case HitResult.NO_EFFECT:
this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) }));
break;
case HitResult.IMMUNE:
case HitResult.NO_EFFECT:
console.error("Unhandled move immunity!");
this.scene.queueMessage(i18next.t("battle:hitResultImmune", { pokemonName: this.name }));
break;
case HitResult.ONE_HIT_KO:
this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO"));
break;
}
}
@ -2263,15 +2244,23 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
if (damage) {
destinyTag?.lapse(source, BattlerTagLapseType.CUSTOM);
const attacker = this.scene.getPokemonById(source.id)!; // TODO: is this bang correct?
destinyTag?.lapse(attacker, BattlerTagLapseType.CUSTOM);
}
}
break;
case MoveCategory.STATUS:
if (!cancelled.value && typeMultiplier === 0) {
if (!typeless) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier);
}
if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, false, typeMultiplier);
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, move, cancelled, false, typeMultiplier));
}
if (!typeMultiplier.value) {
this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) }));
}
result = (typeMultiplier === 0) ? HitResult.NO_EFFECT : HitResult.STATUS;
result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS;
break;
}
@ -3928,7 +3917,7 @@ export class EnemyPokemon extends Pokemon {
* Attack moves are given extra multipliers to their base benefit score based on
* the move's type effectiveness against the target and whether the move is a STAB move.
*/
const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed);
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove);
if (target.isPlayer() !== this.isPlayer()) {
targetScore *= effectiveness;
if (this.isOfType(move.type)) {

View File

@ -2913,7 +2913,7 @@
},
"zippyZap": {
"name": "Zippy Zap",
"effect": "The user attacks the target with bursts of electricity at high speed. This move always goes first and results in a critical hit."
"effect": "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness."
},
"splishySplash": {
"name": "Splishy Splash",
@ -3807,4 +3807,4 @@
"name": "Malignant Chain",
"effect": "The user pours toxins into the target by wrapping them in a toxic, corrosive chain. This may also leave the target badly poisoned."
}
}
}

View File

@ -16,7 +16,7 @@
"invalidLoginUsername": "El usuario no es válido",
"invalidRegisterUsername": "El usuario solo puede contener letras, números y guiones bajos",
"invalidLoginPassword": "La contraseña no es válida",
"invalidRegisterPassword": "La contraseña debe tener 6 o más caracteres.",
"invalidRegisterPassword": "Contraseña debe tener 6 o más caracter.",
"usernameAlreadyUsed": "El usuario ya está en uso",
"accountNonExistent": "El usuario no existe",
"unmatchingPassword": "La contraseña no coincide",
@ -37,19 +37,12 @@
"weeklyRankings": "Rankings Semanales",
"noRankings": "Sin Rankings",
"positionIcon": "#",
"usernameScoreboard": "Usuario",
"score": "Puntos",
"wave": "Oleada",
"loading": "Cargando…",
"loadingAsset": "Cargando recurso: {{assetName}}",
"playersOnline": "Jugadores en Línea",
"yes": "Sí",
"no": "No",
"disclaimer": "AVISO",
"disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida\n de datos de guardado), cambiar sin avisar, y puede o no puede ser actualizado hasta ser completado.",
"choosePokemon": "Elige un Pokémon.",
"renamePokemon": "Renombrar Pokémon.",
"rename": "Renombrar",
"nickname": "Apodo",
"errorServerDown": "¡Ups! Ha habido un problema al contactar con el servidor.\n\nPuedes mantener esta ventana abierta, el juego se reconectará automáticamente."
}
"disclaimerDescription": "Este juego es un producto inacabado; puede tener problemas de jugabilidad (incluyendo la posible pérdida\n de datos de guardado),cambiar sin avisar, y puede o no puede ser actualizado hasta ser completado.",
"errorServerDown": "¡Ups! Ha habido un problema al contactar con el servidor.\n\nPuedes mantener esta ventana abierta,\nel juego se reconectará automáticamente."
}

View File

@ -97,10 +97,6 @@
"name": "MT{{moveId}} - {{moveName}}",
"description": "Enseña {{moveName}} a un Pokémon."
},
"TmModifierTypeWithInfo": {
"name": "MT{{moveId}} - {{moveName}}",
"description": "Enseña {{moveName}} a un Pokémon\n(Mantén pulsado C o Shift para más info)."
},
"EvolutionItemModifierType": {
"description": "Hace que ciertos Pokémon evolucionen."
},
@ -133,12 +129,12 @@
"name": "Caramelorarísimo"
},
"MEGA_BRACELET": {
"name": "Megapulsera",
"description": "Las megapiedras se vuelven disponibles."
"name": "Mega-aro",
"description": "Las Megapiedras están disponibles."
},
"DYNAMAX_BAND": {
"name": "Maximuñequera",
"description": "Las maxisetas se vuelven disponibles."
"description": "Las Maxisetas están disponibles."
},
"TERA_ORB": {
"name": "Orbe Teracristal",
@ -158,42 +154,42 @@
"name": "Hiperpoción"
},
"MAX_POTION": {
"name": "Máx. poción"
"name": "Máx. Poción"
},
"FULL_RESTORE": {
"name": "Restau. todo"
"name": "Restau. Todo"
},
"REVIVE": {
"name": "Revivir"
},
"MAX_REVIVE": {
"name": "Máx. revivir"
"name": "Máx. Revivir"
},
"FULL_HEAL": {
"name": "Cura total"
"name": "Cura Total"
},
"SACRED_ASH": {
"name": "Ceniza sagrada"
"name": "Cen. Sagrada"
},
"REVIVER_SEED": {
"name": "Semilla revivir",
"name": "Semilla Revivir",
"description": "Revive al portador con la mitad de sus PS al debilitarse por un golpe directo."
},
"WHITE_HERB": {
"name": "Hierba blanca",
"description": "Un objeto que puede llevar un Pokémon. Restaurará cualquier estadística reducida en combate."
"name": "White Herb",
"description": "An item to be held by a Pokémon. It will restore any lowered stat in battle."
},
"ETHER": {
"name": "Éter"
},
"MAX_ETHER": {
"name": "Éter máx."
"name": "Éter Máx."
},
"ELIXIR": {
"name": "Elixir"
},
"MAX_ELIXIR": {
"name": "Elixir máx."
"name": "Elixir Máx."
},
"PP_UP": {
"name": "Más PP"
@ -208,10 +204,10 @@
"name": "Superincienso"
},
"MAX_LURE": {
"name": "Incienso máximo"
"name": "Incienso Máximo"
},
"MEMORY_MUSHROOM": {
"name": "Seta recuerdo",
"name": "Seta Recuerdo",
"description": "Recuerda un movimiento olvidado de un Pokémon."
},
"EXP_SHARE": {
@ -219,8 +215,8 @@
"description": "Los que no combatan reciben el 20% de la EXP."
},
"EXP_BALANCE": {
"name": "Equilibrador EXP",
"description": "Da una mayor parte de la EXP recibida a los miembros del equipo que tengan menos nivel."
"name": "Equilibrar EXP",
"description": "Da mayor parte de la EXP recibida a los miembros del equipo que tengan menos nivel."
},
"OVAL_CHARM": {
"name": "Amuleto Oval",
@ -236,13 +232,13 @@
"name": "Amuleto EXP Dorado"
},
"LUCKY_EGG": {
"name": "Huevo suerte"
"name": "Huevo Suerte"
},
"GOLDEN_EGG": {
"name": "Huevo dorado"
"name": "Huevo Dorado"
},
"SOOTHE_BELL": {
"name": "Camp. alivio"
"name": "Camp. Alivio"
},
"SCOPE_LENS": {
"name": "Periscopio",
@ -253,7 +249,7 @@
"description": "Puerro muy largo y duro que aumenta la probabilidad de asestar un golpe crítico. Debe llevarlo Farfetch'd."
},
"EVIOLITE": {
"name": "Mineral evolutivo",
"name": "Mineral Evolutivo",
"description": "Roca misteriosa. El Pokémon portador aumentará su Defensa y su Defensa Especial si aún puede evolucionar."
},
"SOUL_DEW": {
@ -270,7 +266,7 @@
"name": "Real de oro"
},
"AMULET_COIN": {
"name": "Moneda amuleto",
"name": "Moneda Amuleto",
"description": "Aumenta el dinero ganado en un 20%."
},
"GOLDEN_PUNCH": {
@ -283,10 +279,10 @@
},
"LOCK_CAPSULE": {
"name": "Cápsula candado",
"description": "Permite bloquear las rarezas de los objetos al refrescar objetos."
"description": "Le permite bloquear las rarezas de los objetos al cambiar de objetos."
},
"GRIP_CLAW": {
"name": "Garra garfio"
"name": "Garra Garfio"
},
"WIDE_LENS": {
"name": "Lupa"
@ -298,24 +294,20 @@
"name": "Amuleto curación",
"description": "Aumenta la efectividad de los movimientos y objetos de curacion de PS en un 10% (excepto revivir)."
},
"CANDY_JAR": {
"name": "Tarrón de caramelos",
"description": "Aumenta la cantidad de niveles otorgados por los ítems Caramelos Raros en 1."
},
"BERRY_POUCH": {
"name": "Saco bayas",
"description": "Añade un 30% de posibilidades de que una baya no se gaste al usarla."
"name": "Saco Bayas",
"description": "Agrega un 30% de posibilidades de que una baya usada no se consuma."
},
"FOCUS_BAND": {
"name": "Banda aguante",
"name": "Cinta Focus",
"description": "Agrega un 10% de probabilidad de resistir un ataque que lo debilitaría."
},
"QUICK_CLAW": {
"name": "Garra rápida",
"name": "Garra Rápida",
"description": "Agrega un 10% de probabilidad de atacar primero independientemente de la velocidad (después de la prioridad)."
},
"KINGS_ROCK": {
"name": "Roca del rey",
"name": "Roca del Rey",
"description": "Agrega un 10% de probabilidad de que un ataque haga que el oponente retroceda."
},
"LEFTOVERS": {
@ -323,7 +315,7 @@
"description": "Cura 1/16 de los PS máximo de un Pokémon cada turno."
},
"SHELL_BELL": {
"name": "Cascabel concha",
"name": "Camp Concha",
"description": "Cura 1/8 del daño infligido por un Pokémon."
},
"TOXIC_ORB": {
@ -335,15 +327,15 @@
"description": "Extraña esfera que causa quemaduras a quien la usa en combate."
},
"BATON": {
"name": "Testigo",
"name": "Relevo",
"description": "Permite pasar los efectos al cambiar de Pokémon, también evita las trampas."
},
"SHINY_CHARM": {
"name": "Amuleto iris",
"name": "Amuleto Iris",
"description": "Aumenta drásticamente la posibilidad de que un Pokémon salvaje sea Shiny."
},
"ABILITY_CHARM": {
"name": "Amuleto habilidad",
"name": "Amuleto Habilidad",
"description": "Aumenta drásticamente la posibilidad de que un Pokémon salvaje tenga una habilidad oculta."
},
"IV_SCANNER": {
@ -354,60 +346,60 @@
"name": "Punta ADN"
},
"MINI_BLACK_HOLE": {
"name": "Mini agujero negro"
"name": "Mini Agujero Negro"
},
"GOLDEN_POKEBALL": {
"name": "Poké Ball Dorada",
"description": "Agrega 1 opción de objeto extra al final de cada combate."
},
"ENEMY_DAMAGE_BOOSTER": {
"name": "Ficha de daño",
"name": "Ficha Daño",
"description": "Aumenta el daño en un 5%."
},
"ENEMY_DAMAGE_REDUCTION": {
"name": "Ficha de protección",
"name": "Ficha Protección",
"description": "Reduce el daño recibido en un 2,5%."
},
"ENEMY_HEAL": {
"name": "Ficha de curación",
"name": "Ficha Curación",
"description": "Cura el 2% de los PS máximo en cada turno."
},
"ENEMY_ATTACK_POISON_CHANCE": {
"name": "Ficha veneno"
"name": "Ficha Veneno"
},
"ENEMY_ATTACK_PARALYZE_CHANCE": {
"name": "Ficha parálisis"
"name": "Ficha Parálisis"
},
"ENEMY_ATTACK_BURN_CHANCE": {
"name": "Ficha quemadura"
"name": "Ficha Quemadura"
},
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": {
"name": "Ficha cura total",
"name": "Ficha Cura Total",
"description": "Agrega un 2.5% de probabilidad cada turno de curar un problema de estado."
},
"ENEMY_ENDURE_CHANCE": {
"name": "Ficha aguante"
"name": "Ficha Aguante"
},
"ENEMY_FUSED_CHANCE": {
"name": "Ficha fusión",
"name": "Ficha Fusión",
"description": "Agrega un 1% de probabilidad de que un Pokémon salvaje sea una fusión."
}
},
"SpeciesBoosterItem": {
"LIGHT_BALL": {
"name": "Bola luminosa",
"name": "Bola Luminosa",
"description": "Asombrosa esfera que aumenta el Ataque y el Ataque Especial. Debe llevarla Pikachu."
},
"THICK_CLUB": {
"name": "Hueso grueso",
"name": "Hueso Grueso",
"description": "Extraño tipo de hueso que potencia los ataques físicos. Debe llevarlo Cubone o Marowak."
},
"METAL_POWDER": {
"name": "Polvo metálico",
"name": "Polvo Metálico",
"description": "Polvo muy fino, pero a la vez poderoso, que aumenta la Defensa. Debe llevarlo Ditto."
},
"QUICK_POWDER": {
"name": "Polvo veloz",
"name": "Polvo Veloz",
"description": "Polvo muy fino, pero a la vez poderoso, que aumenta la Velocidad. Debe llevarlo Ditto."
}
},
@ -421,35 +413,35 @@
"dire_hit": "Crítico X"
},
"TempBattleStatBoosterStatName": {
"ATK": "Ataque",
"DEF": "Defensa",
"SPATK": "Ataq. Esp.",
"SPDEF": "Def. Esp.",
"SPD": "Velocidad",
"ACC": "Precisión",
"CRIT": "Tasa de crítico",
"EVA": "Evasión",
"ATK": "Attack",
"DEF": "Defense",
"SPATK": "Sp. Atk",
"SPDEF": "Sp. Def",
"SPD": "Speed",
"ACC": "Accuracy",
"CRIT": "Critical Hit Ratio",
"EVA": "Evasiveness",
"DEFAULT": "???"
},
"AttackTypeBoosterItem": {
"silk_scarf": "Pañuelo seda",
"black_belt": "Cinturón negro",
"sharp_beak": "Pico afilado",
"poison_barb": "Flecha venenosa",
"soft_sand": "Arena fina",
"hard_stone": "Piedra dura",
"silver_powder": "Polvo plata",
"silk_scarf": "Pañuelo Seda",
"black_belt": "Cinturón Negro",
"sharp_beak": "Pico Afilado",
"poison_barb": "Flecha Venenosa",
"soft_sand": "Arena Fina",
"hard_stone": "Piedra Dura",
"silver_powder": "Polvo Plata",
"spell_tag": "Hechizo",
"metal_coat": "Revest. metálico",
"metal_coat": "Rev. Metálico",
"charcoal": "Carbón",
"mystic_water": "Agua mística",
"miracle_seed": "Semilla milagro",
"mystic_water": "Agua Mística",
"miracle_seed": "Semilla Milagro",
"magnet": "Imán",
"twisted_spoon": "Cuchara torcida",
"twisted_spoon": "Cuchara Torcida",
"never_melt_ice": "Antiderretir",
"dragon_fang": "Colmillo dragón",
"black_glasses": "Gafas de sol",
"fairy_feather": "Pluma feérica"
"dragon_fang": "Colmillo Dragón",
"black_glasses": "Gafas de Sol",
"fairy_feather": "Pluma Hada"
},
"BaseStatBoosterItem": {
"hp_up": "Más PS",
@ -460,38 +452,38 @@
"carbos": "Carburante"
},
"EvolutionItem": {
"NONE": "Ninguno",
"LINKING_CORD": "Cordón unión",
"SUN_STONE": "Piedra solar",
"MOON_STONE": "Piedra lunar",
"LEAF_STONE": "Piedra hoja",
"FIRE_STONE": "Piedra fuego",
"WATER_STONE": "Piedra agua",
"THUNDER_STONE": "Piedra trueno",
"ICE_STONE": "Piedra hielo",
"DUSK_STONE": "Piedra noche",
"DAWN_STONE": "Piedra alba",
"SHINY_STONE": "Piedra día",
"CRACKED_POT": "Tetera agrietada",
"SWEET_APPLE": "Manzana dulce",
"TART_APPLE": "Manzana ácida",
"STRAWBERRY_SWEET": "Confite fresa",
"UNREMARKABLE_TEACUP": "Cuenco mediocre",
"CHIPPED_POT": "Tetera rota",
"BLACK_AUGURITE": "Mineral negro",
"GALARICA_CUFF": "Brazal galanuez",
"GALARICA_WREATH": "Corona galanuez",
"PEAT_BLOCK": "Bloque de turba",
"AUSPICIOUS_ARMOR": "Armadura auspiciosa",
"MALICIOUS_ARMOR": "Armadura maldita",
"MASTERPIECE_TEACUP": "Cuenco exquisito",
"METAL_ALLOY": "Metal compuesto",
"SCROLL_OF_DARKNESS": "Manuscrito sombras",
"SCROLL_OF_WATERS": "Manuscrito aguas",
"SYRUPY_APPLE": "Manzana melosa"
"NONE": "None",
"LINKING_CORD": "Cordón Unión",
"SUN_STONE": "Piedra Solar",
"MOON_STONE": "Piedra Lunar",
"LEAF_STONE": "Piedra Hoja",
"FIRE_STONE": "Piedra Fuego",
"WATER_STONE": "Piedra Agua",
"THUNDER_STONE": "Piedra Trueno",
"ICE_STONE": "Piedra Hielo",
"DUSK_STONE": "Piedra Noche",
"DAWN_STONE": "Piedra Alba",
"SHINY_STONE": "Piedra Día",
"CRACKED_POT": "Tetera Agrietada",
"SWEET_APPLE": "Manzana Dulce",
"TART_APPLE": "Manzana Ácida",
"STRAWBERRY_SWEET": "Confite Fresa",
"UNREMARKABLE_TEACUP": "Cuenco Mediocre",
"CHIPPED_POT": "Tetera Rota",
"BLACK_AUGURITE": "Mineral Negro",
"GALARICA_CUFF": "Brazal Galanuez",
"GALARICA_WREATH": "Corona Galanuez",
"PEAT_BLOCK": "Bloque de Turba",
"AUSPICIOUS_ARMOR": "Armadura Auspiciosa",
"MALICIOUS_ARMOR": "Armadura Maldita",
"MASTERPIECE_TEACUP": "Cuenco Exquisito",
"METAL_ALLOY": "Metal Compuesto",
"SCROLL_OF_DARKNESS": "Manuscrito Sombras",
"SCROLL_OF_WATERS": "Manuscrito Aguas",
"SYRUPY_APPLE": "Manzana Melosa"
},
"FormChangeItem": {
"NONE": "Ninguno",
"NONE": "None",
"ABOMASITE": "Abomasnowita",
"ABSOLITE": "Absolita",
"AERODACTYLITE": "Aerodactylita",
@ -540,70 +532,70 @@
"SWAMPERTITE": "Swampertita",
"TYRANITARITE": "Tyranitarita",
"VENUSAURITE": "Venusaurita",
"BLUE_ORB": "Prisma azul",
"RED_ORB": "Prisma rojo",
"SHARP_METEORITE": "Meteorito afilado",
"HARD_METEORITE": "Meteorito duro",
"SMOOTH_METEORITE": "Meteorito suave",
"ADAMANT_CRYSTAL": "Gran diamansfera",
"LUSTROUS_GLOBE": "Gran lustresfera",
"GRISEOUS_CORE": "Gran griseosfera",
"REVEAL_GLASS": "Espejo veraz",
"BLUE_ORB": "Prisma Azul",
"RED_ORB": "Prisma Rojo",
"SHARP_METEORITE": "Meteorito Afilado",
"HARD_METEORITE": "Meteorito Duro",
"SMOOTH_METEORITE": "Meteorito Suave",
"ADAMANT_CRYSTAL": "Gran Diamansfera",
"LUSTROUS_GLOBE": "Gran Lustresfera",
"GRISEOUS_CORE": "Gran Griseosfera",
"REVEAL_GLASS": "Espejo Veraz",
"GRACIDEA": "Gracídea",
"MAX_MUSHROOMS": "Maxisetas",
"DARK_STONE": "Orbe oscuro",
"LIGHT_STONE": "Orbe claro",
"PRISON_BOTTLE": "Vasija castigo",
"MAX_MUSHROOMS": "MaxiSetas",
"DARK_STONE": "Piedra Oscura",
"LIGHT_STONE": "Piedra Luminosa",
"PRISON_BOTTLE": "Vasija Castigo",
"N_LUNARIZER": "Necroluna",
"N_SOLARIZER": "Necrosol",
"RUSTED_SWORD": "Espada oxidada",
"RUSTED_SHIELD": "Escudo oxidado",
"ICY_REINS_OF_UNITY": "Riendas unión heladas",
"SHADOW_REINS_OF_UNITY": "Riendas unión oscuras",
"WELLSPRING_MASK": "Máscara fuente",
"HEARTHFLAME_MASK": "Máscara horno",
"CORNERSTONE_MASK": "Máscara cimiento",
"RUSTED_SWORD": "Espada Oxidada",
"RUSTED_SHIELD": "Escudo Oxidado",
"ICY_REINS_OF_UNITY": "Riendas Unión Heladas",
"SHADOW_REINS_OF_UNITY": "Riendas Unión Oscuras",
"WELLSPRING_MASK": "Máscara Fuente",
"HEARTHFLAME_MASK": "Máscara Horno",
"CORNERSTONE_MASK": "Máscara Cimiento",
"SHOCK_DRIVE": "FulgoROM",
"BURN_DRIVE": "PiroROM",
"CHILL_DRIVE": "CrioROM",
"DOUSE_DRIVE": "HidroROM",
"ULTRANECROZIUM_Z": "Ultranecrostal Z",
"FIST_PLATE": "Tabla fuerte",
"SKY_PLATE": "Tabla cielo",
"TOXIC_PLATE": "Tabla tóxica",
"EARTH_PLATE": "Tabla terrax",
"STONE_PLATE": "Tabla pétrea",
"INSECT_PLATE": "Tabla bicho",
"SPOOKY_PLATE": "Tabla terror",
"IRON_PLATE": "Tabla acero",
"FLAME_PLATE": "Tabla llama",
"SPLASH_PLATE": "Tabla linfa",
"MEADOW_PLATE": "Tabla pradal",
"ZAP_PLATE": "Tabla trueno",
"MIND_PLATE": "Tabla mental",
"ICICLE_PLATE": "Tabla helada",
"DRACO_PLATE": "Tabla draco",
"DREAD_PLATE": "Tabla oscura",
"PIXIE_PLATE": "Tabla duende",
"BLANK_PLATE": "Tabla neutra",
"LEGEND_PLATE": "Tabla legendaria",
"FIGHTING_MEMORY": "Disco lucha",
"FLYING_MEMORY": "Disco volador",
"POISON_MEMORY": "Disco veneno",
"GROUND_MEMORY": "Disco tierra",
"ROCK_MEMORY": "Disco roca",
"BUG_MEMORY": "Disco bicho",
"GHOST_MEMORY": "Disco fantasma",
"STEEL_MEMORY": "Disco acero",
"FIRE_MEMORY": "Disco fuego",
"WATER_MEMORY": "Disco agua",
"GRASS_MEMORY": "Disco planta",
"ELECTRIC_MEMORY": "Disco eléctrico",
"PSYCHIC_MEMORY": "Disco psíquico",
"ICE_MEMORY": "Disco hielo",
"DRAGON_MEMORY": "Disco dragón",
"DARK_MEMORY": "Disco siniestro",
"FAIRY_MEMORY": "Disco hada",
"BLANK_MEMORY": "Disco en blanco"
"FIST_PLATE": "Tabla Fuerte",
"SKY_PLATE": "Tabla Cielo",
"TOXIC_PLATE": "Tabla Tóxica",
"EARTH_PLATE": "Tabla Terrax",
"STONE_PLATE": "Tabla Pétrea",
"INSECT_PLATE": "Tabla Bicho",
"SPOOKY_PLATE": "Tabla Terror",
"IRON_PLATE": "Tabla Acero",
"FLAME_PLATE": "Tabla Llama",
"SPLASH_PLATE": "Tabla Linfa",
"MEADOW_PLATE": "Tabla Pradal",
"ZAP_PLATE": "Tabla Trueno",
"MIND_PLATE": "Tabla Mental",
"ICICLE_PLATE": "Tabla Helada",
"DRACO_PLATE": "Tabla Draco",
"DREAD_PLATE": "Tabla Oscura",
"PIXIE_PLATE": "Tabla Duende",
"BLANK_PLATE": "Tabla Neutra",
"LEGEND_PLATE": "Tabla Legendaria",
"FIGHTING_MEMORY": "Disco Lucha",
"FLYING_MEMORY": "Disco Volador",
"POISON_MEMORY": "Disco Veneno",
"GROUND_MEMORY": "Disco Tierra",
"ROCK_MEMORY": "Disco Roca",
"BUG_MEMORY": "Disco Bicho",
"GHOST_MEMORY": "Disco Fantasma",
"STEEL_MEMORY": "Disco Acero",
"FIRE_MEMORY": "Disco Fuego",
"WATER_MEMORY": "Disco Agua",
"GRASS_MEMORY": "Disco Planta",
"ELECTRIC_MEMORY": "Disco Eléctrico",
"PSYCHIC_MEMORY": "Disco Psíquico",
"ICE_MEMORY": "Disco Hielo",
"DRAGON_MEMORY": "Disco Dragón",
"DARK_MEMORY": "Disco Siniestro",
"FAIRY_MEMORY": "Disco Hada",
"BLANK_MEMORY": "Disco Blanco"
}
}
}

View File

@ -3807,4 +3807,4 @@
"name": "Cadena Virulenta",
"effect": "Apresa al objetivo con una cadena hecha de ponzoña que le inocula toxinas para minarle las fuerzas. Puede envenenar gravemente."
}
}
}

View File

@ -12,7 +12,7 @@
"typeImmunityHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} évite\nles dégâts avec {{abilityName}} !",
"disguiseAvoidedDamage": "Le déguisement de {{pokemonNameWithAffix}}\ntombe !",
"moveImmunity": "Ça naffecte pas {{pokemonNameWithAffix}}…",
"moveImmunity": "Ça n'affecte pas {{pokemonNameWithAffix}}…",
"reverseDrain": "{{pokemonNameWithAffix}} aspire\nle suintement !",
"postDefendTypeChange": "{{abilityName}} de {{pokemonNameWithAffix}}\nle transforme en type {{typeName}} !",
"postDefendContactDamage": "{{pokemonNameWithAffix}} est blessé\npar son talent {{abilityName}} !",
@ -23,7 +23,7 @@
"postAttackStealHeldItem": "{{pokemonNameWithAffix}} vole\nlobjet {{stolenItemType}} de {{defenderName}} !",
"postDefendStealHeldItem": "{{pokemonNameWithAffix}} vole\nlobjet {{stolenItemType}} de {{attackerName}} !",
"copyFaintedAllyAbility": "{{pokemonNameWithAffix}} reçoit\nle talent {{abilityName}} !",
"intimidateImmunity": "{{abilityName}} de {{pokemonNameWithAffix}}\nlempêche dêtre intimidé !",
"intimidateImmunity": "{{abilityName}} de {{pokemonNameWithAffix}}\nlempêche d'être intimidé !",
"postSummonAllyHeal": "{{pokemonNameWithAffix}} boit le thé\npréparé par {{pokemonName}} !",
"postSummonClearAllyStats": "Les stats de {{pokemonNameWithAffix}}\nsont revenues à la normale!",
"postSummonTransform": "{{pokemonNameWithAffix}} prend\nlapparence de {{targetName}} !",
@ -59,4 +59,4 @@
"postSummonTabletsOfRuin": "Le Bois du Fléau de {{pokemonNameWithAffix}}\naffaiblit l{{statName}} des Pokémon alentour !",
"postSummonBeadsOfRuin": "Les Perles du Fléau de {{pokemonNameWithAffix}}\naffaiblissent la {{statName}} des Pokémon alentour !",
"preventBerryUse": "{{pokemonNameWithAffix}} est tendu\net ne peut plus manger de Baies !"
}
}

View File

@ -469,11 +469,11 @@
},
"honeyGather": {
"name": "Cherche Miel",
"description": "Le Pokémon trouve du Miel après un combat et est directement revendu contre de largent."
"description": "The Pokémon gathers Honey after a battle. The Honey is then sold for money."
},
"frisk": {
"name": "Fouille",
"description": "Lorsquil entre en combat, le Pokémon peut vérifier la capacité dun Pokémon adverse."
"description": "Lorsqu'il entre en combat, le Pokémon peut vérifier la capacité d'un Pokémon adverse."
},
"reckless": {
"name": "Téméraire",
@ -1239,4 +1239,4 @@
"name": "Emprise Toxique",
"description": "Lorsque Pêchaminus empoisonne un Pokémon grâce à lune de ses capacités, ce dernier devient également confus."
}
}
}

View File

@ -62,7 +62,7 @@
"name": "Caïd"
},
"HealAchv": {
"description": "Soigner {{healAmount}} {{HP}} en une fois avec une capacité,\nun talent ou un objet tenu."
"description": "Soigner {{healAmount}} {{HP}} en une fois avec une capacité, un talent ou un objet tenu."
},
"1000_HEAL": {
"name": "Médecin"
@ -261,4 +261,4 @@
"name": "Du premier coup !",
"description": "Terminer un challenge « Nouveau départ »."
}
}
}

View File

@ -36,7 +36,7 @@
"name": "One Punch Man"
},
"HealAchv": {
"description": "Soigner {{healAmount}} {{HP}} en une fois avec une capacité,\nun talent ou un objet tenu."
"description": "Soigner {{healAmount}} {{HP}} en une fois avec une capacité, un talent ou un objet tenu."
},
"250_HEAL": {
"name": "Infirmier"
@ -261,4 +261,4 @@
"name": "Du premier coup !",
"description": "Terminer un challenge « Nouveau départ »."
}
}
}

View File

@ -1,3 +1,3 @@
{
"generation": "{{generation}}"
}
"generation": "Génération {{generation}}"
}

View File

@ -1,5 +1,5 @@
{
"music": " : ",
"music": "Musique : ",
"missing_entries": "{{name}}",
"battle_kanto_champion": "N2B2 - Vs. Maitre de Kanto",
"battle_johto_champion": "N2B2 - Vs. Maitre de Johto",
@ -83,41 +83,41 @@
"battle_galactic_boss": "DÉPS - Vs. Hélio",
"battle_plasma_boss": "N2B2 - Vs. Ghetis",
"battle_flare_boss": "XY - Vs. Lysandre",
"abyss": "PDM EdC - Cratère Obscur",
"badlands": "PDM EdC - Vallée Stérile",
"beach": "PDM EdC - Falaise Trempée",
"cave": "PDM EdC - Pic Céleste (grotte)",
"construction_site": "PDM EdC - Carrière Rocher",
"desert": "PDM EdC - Désert du Nord",
"dojo": "PDM EdC - Dojo Ossatueur",
"end": "PDM EdC - Tour Céleste",
"factory": "PDM EdC - Ruines Cachées",
"fairy_cave": "PDM EdC - Caverne Étoile",
"forest": "PDM EdC - Forêt Crépuscule",
"grass": "PDM EdC - Bois aux Pommes",
"graveyard": "PDM EdC - Forêt Trompeuse",
"ice_cave": "PDM EdC - Montagne Glacier",
"island": "PDM EdC - Côte Escarpée",
"abyss": "PDM EdS - Cratère Obscur",
"badlands": "PDM EdS - Vallée Stérile",
"beach": "PDM EdS - Falaise Trempée",
"cave": "PDM EdS - Pic Céleste (grotte)",
"construction_site": "PDM EdS - Carrière Rocher",
"desert": "PDM EdS - Désert du Nord",
"dojo": "PDM EdS - Dojo Ossatueur",
"end": "PDM EdS - Tour Céleste",
"factory": "PDM EdS - Ruines Cachées",
"fairy_cave": "PDM EdS - Caverne Étoile",
"forest": "PDM EdS - Forêt Crépuscule",
"grass": "PDM EdS - Bois aux Pommes",
"graveyard": "PDM EdS - Forêt Trompeuse",
"ice_cave": "PDM EdS - Montagne Glacier",
"island": "PDM EdS - Côte Escarpée",
"jungle": "Lmz - Jungle",
"laboratory": "Firel - Laboratory",
"lake": "PDM EdC - Caverne Cristal",
"meadow": "PDM EdC - Pic Céleste (forêt)",
"lake": "PDM EdS - Caverne Cristal",
"meadow": "PDM EdS - Pic Céleste (forêt)",
"metropolis": "Firel - Metropolis",
"mountain": "PDM EdC - Mont Corne",
"plains": "PDM EdC - Pic Céleste (prairie)",
"power_plant": "PDM EdC - Plaines Élek",
"ruins": "PDM EdC - Ruine Scellée",
"mountain": "PDM EdS - Mt Corne",
"plains": "PDM EdS - Pic Céleste (prairie)",
"power_plant": "PDM EdS - Plaines Élek",
"ruins": "PDM EdS - Ruine Scellée",
"sea": "Andr06 - Marine Mystique",
"seabed": "Firel - Seabed",
"slum": "Andr06 - Sneaky Snom",
"snowy_forest": "PDM EdC - Pic Céleste (plaine enneigée)",
"snowy_forest": "PDM EdS - Pic Céleste (plaine enneigée)",
"space": "Firel - Aether",
"swamp": "PDM EdC - Mer Fermée",
"tall_grass": "PDM EdC - Forêt Brumeuse",
"temple": "PDM EdC - Grotte Égide",
"town": "PDM EdC - Donjon aléatoire - Thème 3",
"volcano": "PDM EdC - Grotte Étuve",
"wasteland": "PDM EdC - Terres Illusoires",
"swamp": "PDM EdS - Mer Fermée",
"tall_grass": "PDM EdS - Forêt Brumeuse",
"temple": "PDM EdS - Grotte Égide",
"town": "PDM EdS - Donjon aléatoire - Thème 3",
"volcano": "PDM EdS - Grotte Étuve",
"wasteland": "PDM EdS - Terres Illusoires",
"encounter_ace_trainer": "NB - Regards croisés (Topdresseur·euse)",
"encounter_backpacker": "NB - Regards croisés (Randonneur·euse)",
"encounter_clerk": "NB - Regards croisés (Employé·e)",
@ -133,6 +133,6 @@
"encounter_twins": "NB - Regards croisés (Jumelles)",
"encounter_youngster": "NB - Regards croisés (Gamin)",
"heal": "NB - Soin de Pokémon",
"menu": "PDM EdC - Bienvenue dans le monde de Pokémon !",
"title": "PDM EdC - Menu Principal"
}
"menu": "PDM EdS - Bienvenue dans le monde de Pokémon !",
"title": "PDM EdS - Menu Principal"
}

View File

@ -1,7 +1,7 @@
{
"blue_red_double": {
"encounter": {
"1": "Blue : Hé Red, montrons-lui de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !"
"1": "Blue : Hé Red, montrons-leur de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !"
},
"victory": {
"1": "Blue : Cétait un magnifique combat !\n$Red : …"
@ -79,4 +79,4 @@
"1": "Peterson : Ça cest du rock !\n$Rosemary : Frérot…"
}
}
}
}

View File

@ -1,7 +1,7 @@
{
"blue_red_double": {
"encounter": {
"1": "Blue : Hé Red, montrons-lui de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !"
"1": "Blue : Hé Red, montrons-leur de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !"
},
"victory": {
"1": "Blue : Cétait un magnifique combat !\n$Red : …"
@ -79,4 +79,4 @@
"1": "Peterson : Ça cest du rock !\n$Rosemary : Frérot…"
}
}
}
}

View File

@ -38,7 +38,7 @@
"3": "Je te connais pas. Ça te dis de te battre ?",
"4": "Prenons du bon temps avec ce combat Pokémon !",
"5": "Je vais tapprendre à te battre avec tes Pokémon !",
"6": "Un combat doit toujours être pris au sérieux.\nTes prête à te battre ?",
"6": "Un combat doit être pris au sérieux. Tes prête à te battre ?",
"7": "Tu seras pas jeune éternellement. Tas quune chance pendant un combat. Bientôt, tu seras plus quun souvenir.",
"8": "Tu ferais mieux dy aller doucement avec moi. Mais je vais me battre sérieusement !",
"9": "Je mennuie à lécole. Ya rien à y faire. *Baille*\nJe me bats juste pour passer le temps."
@ -69,7 +69,7 @@
"defeat": {
"1": "Tu ne devrais pas ténerver sur tes Pokémon, même après une défaite.",
"2": "Alors ? Pas mal mes Pokémon, hein ? Je suis fait pour ça.",
"3": "Peu importe à quel point taimes tes Pokémon, il faut toujours de la discipline sils se comportent mal."
"3": "Peut importe à quel point taimes tes Pokémon, il faut toujours de la discipline sils se comportent mal."
}
},
"breeder_female": {
@ -148,7 +148,7 @@
},
"victory": {
"1": "Très bien… Tas de bons Pokémon…",
"2": "Quoi ?! Mais cest moi le génie des combats !",
"2": "Quoi ?! Mais c'est moi le génie des combats !",
"3": "Évidemment que tes le personnage principal !",
"4": "OK ! OK ! Tu pourrais être une Topdresseuse !"
},
@ -169,98 +169,50 @@
},
"rocket_grunt": {
"encounter": {
"1": "Nous sommes de retour !",
"2": "Ça bosse dur, ici ! Alors du balai !",
"3": "File-nous tes Pokémon ou tu vas gouter à la colère de la Team Rocket !",
"4": "Sois témoin de ce quest une vraie terreur de la Team Rocket!",
"5": "Hé gamine ! Moi être guy member of la Team Rocket !"
"1": "Nous sommes de retour !"
},
"victory": {
"1": "Une fois de plus la Team Rocket senvole vers dautres cieux !",
"2": "Mince! Jai laissé tomber\nla Clé Ascenseur !",
"3": "Jai tout foiré !",
"4": "Mes compagnons vont me venger !",
"5": "Toi dire quoi ? Forget que tu mas vu !\nYou nas rien seen !"
"1": "Une fois de plus la Team Rocket senvole vers dautres cieux !"
}
},
"magma_grunt": {
"encounter": {
"1": "Nespère pas recevoir de la pitié si tu te mets sur le chemin de la Team Magma !",
"2": "Ne te mêle pas de nos affaires ! On va rendre ce monde meilleur !",
"3": "Hors de mon chemin ! La Team Magma na pas de temps pour les gamins !",
"4": "Jespère que tas quelques marshmallows, car ça va chauffer !",
"5": "On va utiliser le puissance dun volcan ! Ça va être… explosif ! Tu las… ? Héhé !"
"1": "Nespère pas recevoir de la pitié si tu te mets sur le chemin de la Team Magma !"
},
"victory": {
"1": "Je…?\nJai perdu ?!",
"2": "Je peux pas croire que jai pas pris mon déjeuner juste pour ça…",
"3": "Impossible ! Tes quune gosse !",
"4": "Aahhh…\nJaurais dû directement rentrer à la planque…",
"5": "Tu mas démoli… Tu crois que le boss va suspendre mon salaire ?"
"1": "Je…?\nJai perdu ?!"
}
},
"aqua_grunt": {
"encounter": {
"1": "Aucune pitié si tu te mets sur le chemin de la Team Aqua, même pour un gamin !",
"2": "Grrr…\nTu as eu le culot de topposer à la Team Aqua !",
"3": "Je vais te liquéfier !\nEt ce sera pas quà cause des mes Pokémon Eau !",
"4": "Nous, la Team Aqua, existons pour le bien commun !",
"5": "Prépare-toi à te faire emporter par le courant de…\nEuh… Mes Pokémon ! Oui, mes Pokémon !"
"1": "Aucune pitié si tu te mets sur le chemin de la Team Aqua, même pour une gamine !"
},
"victory": {
"1": "Comment ça ?",
"2": "Ah, javais pas prévu dêtre gêné par un mouflet qui se mêle de tout !",
"3": "Jai perdu ?! Super, jai plus quà nager jusquà la planque maintenant…",
"4": "Oh non quelle angoisse…\nLe boss va me démonter…",
"5": "Je suis battu… Tu penses que le boss va me faire subir le supplice de la planche ?…"
"1": "Comment ça ?"
}
},
"galactic_grunt": {
"encounter": {
"1": "Ne te mets pas en travers de la Team Galaxie !",
"2": "Sois témoin de la puissance de notre technologie et du futur qui se profile !",
"3": "Au nom de la Team Galaxie, jéliminerai quiconque se mettera sur notre route !",
"4": "Prépare ta défaite !",
"5": "Jespère que tes prête à te prendre une raclée de lespace !"
"1": "Ne te mets pas en travers de la Team Galaxie !"
},
"victory": {
"1": "Désactivation…",
"2": "Cet échec nest quune poussière face à nos ambitions débordantes.",
"3": "Notre projet est bien plus important que cette défaite.",
"4": "Comment ?!",
"5": "Note à moi-même :\nMentrainer aux combats Pokémon. Ça urge…"
"1": "Désactivation…"
}
},
"plasma_grunt": {
"encounter": {
"1": "Pas de quatiers à ceux qui ne suivent pas notre idéal !",
"2": "Si je gagne, tu relâches tous tes Pokémon !",
"3": "Si tu te mets en travers de la Team Plasma, je moccuperai de toi personnellement !",
"4": "La Team Plasma va libérer les Pokémon de tous les humains égoïstes dans ton genre !",
"5": "Nos coupes sont lunaires… Mais en combat ?\nTu vas vite le découvrir."
"1": "Pas de quatiers à ceux qui ne suivent pas notre idéal !"
},
"victory": {
"1": "Plasmaaaaaaaaa !",
"2": "Comment ai-je pu perdre…",
"3": "… Ce Pokémon est nul, jvais aller en voler de meilleurs !",
"4": "Les plans ambitieux connaissent toujours leurs lots dinterruptions.",
"5": "Cest mauvais… MAUVAIS MAUVAIS MAUVAIS MAUVAIS !\nVa falloir battre en retraite, cest la méga cata !"
"1": "Plasmaaaaaaaaa !"
}
},
"flare_grunt": {
"encounter": {
"1": "Tes Pokémon ne sont pas dignes de lélégance de la Team Flare.",
"2": "Tas des lunettes de soleil jespère ?\nCar prépare-toi à être éblouie !",
"3": "La Team Flare va purifier ce monde de toute imperfection !",
"4": "Prépare-toi à découvrir lindiscutable sens du style de la Team Flare !",
"5": "La mode, cest important !"
"1": "Le style et le bon gout, il ny a que ça qui compte !"
},
"victory": {
"1": "Mon futur na pas lair si radieux.",
"2": "Les combats semblent être plus complexes que je le pensais.\nRetour aux planches à dessin.",
"3": "Ehhhh ?! Jai perdu ?!",
"4": "Même dans la défaite, lélégance de la Team Flare continue de rayonner sur ce monde.",
"5": "Jappelle pas ça perdre, jappelle ça échouer avec panache !"
"1": "Mon futur me semble guère radieux."
}
},
"rocket_boss_giovanni_1": {
@ -271,7 +223,7 @@
"1": "QUOI ? IMPOSSIBLE !"
},
"defeat": {
"1": "Retiens bien. Ton incapacité à évaluer ta propre force est\nla démonstration claire que tu nes encore quune gamine."
"1": "Retiens bien. Ton incapacité à évaluer ta propre force est\nla démonstration claire que tu n'es encore quune gamine."
}
},
"rocket_boss_giovanni_2": {
@ -384,77 +336,6 @@
"1": "Les Pokémon… Ne devraient plus exister."
}
},
"brock": {
"encounter": {
"1": "Mon expertise des types Roche va te mettre au sol ! En garde !",
"2": "Tu veux toujours te battre avec moi ? Même en sachant que tu vas perdre ?",
"3": "Laisse-moi de montrer la véritable force de mes Pokémon Roche !"
},
"victory": {
"1": "Jétais trop sûr de moi, cest pour ça que jai perdu.",
"2": "Ce monde est vaste ! Je suis honoré davoir pu taffronter.",
"3": "Peut-être bien que je naurais pas dû abandonner ma vocation dÉleveur…"
},
"defeat": {
"1": "La défense est la meilleure des attaques !\nTelle est ma méthode !",
"2": "Viens étudier des roches avec moi la prochaine fois si tu veux apprendre à mieux les aborder !",
"3": "Tout ce temps à voyager autour du monde paie enfin !"
}
},
"misty": {
"encounter": {
"1": "Ma tactique ? Attaquer avec des Pokémon Eau !",
"2": "Je vais te prouver le tsunami que sont mes Pokémon aquatiques !",
"3": "Mon rêve, cétait de voyager et de défier des Dresseurs super forts. Seras-tu à la hauteur ?"
},
"victory": {
"1": "OK. Tes pas naze… Je le reconnais…",
"2": "Pfff… Tas juste eu de la chance hein ?!",
"3": "Ouah ! Tes super balèze !"
},
"defeat": {
"1": "Quen dis-tu? Cest ça, la puissance des Pokémon Eau !",
"2": "Jespère que tas pris note des élégantes techniques de nage de mes Pokémon !",
"3": "Tes Pokémon ne jouent visiblement pas dans le même bassin…"
}
},
"lt_surge": {
"encounter": {
"1": "Tas pas froid aux yeux, soldat ! Les combats Pokémon, cest la guerre !",
"2": "Tu as du guts pour venir me fight ici ! Je vais te shock !",
"3": "Compte tes dents, tu vas morfler !\nMes Pokémon Électrik vont tatomiser !"
},
"victory": {
"1": "Whoo ! Tiras loin toi.",
"2": "Oh noes ! Mes tricks électriques sont à plat…\nYou are very fortiche!",
"3": "Tu es very costaud ! Je vais training very dur mes Pokémon, moi too, et on sera Number One !"
},
"defeat": {
"1": "Oh yeah !\nMes Pokémon Électrik sont les best du monde !",
"2": "Oh yeah, baby ! I am trop fort !",
"3": "Une combat Pokémon, cest comme une guerre et tas eu droit à une bataille de premier ordre !"
}
},
"erika": {
"encounter": {
"1": "Il fait beau, aujourdhui, nest-ce pas… ?\nQuoi un combat… ? Très bien…",
"2": "Larrangement floral est ma spécialité, et mes Pokémon sont de type Plante. Quoi ? Tu veux te battre ?",
"3": "Il fait beau… Le soleil brille… Les plantes bourgeonnent… Je mennuie…",
"4": "Voir un tel jardin rempli de fleurs est si apaisant…"
},
"victory": {
"1": "Bien joué, cest mértié.",
"2": "Dommage, on samusait si bien…",
"3": "Oh non, le combat est terminé…",
"4": "Aaah, ça fait du bien !\nMerci, jen avais besoin."
},
"defeat": {
"1": "Jai failli mendormir…",
"2": "Oh non… Mes Pokémon Plante ont lair de tavoir bien endormie…",
"3": "Ce combat était si apaisant…",
"4": "Oh non… Cest tout ?"
}
},
"flare_boss_lysandre_2": {
"encounter": {
"1": "Ton futur ou le mien…\nVoyons lequel mérite plus daboutir."
@ -468,7 +349,7 @@
},
"rival": {
"encounter": {
"1": "@c{smile}Ah, te voilà ! Je tai cherchée partout ! Je savais que tétais pressée de partir, mais je mattendais quand même à un au revoir…\n$@c{smile_eclosed}Tas finalement décidé de réaliser ton rêve ?\nJai peine à y croire.\n$@c{serious_smile_fists}Vu que tes là, ça te dis un petit combat ?\nJe voudrais quand même massurer que tes prête.\n$@c{serious_mopen_fists}Surtout ne te retiens pas et donne-moi tout ce que tas !"
"1": "@c{smile}Ah, je te cherchais ! Je savais que tétais pressée de partir, mais je mattendais quand même à un au revoir…\n$@c{smile_eclosed}Tas finalement décidé de réaliser ton rêve ?\nJai peine à y croire.\n$@c{serious_smile_fists}Vu que tes là, ça te dis un petit combat ?\nJe voudrais quand même massurer que tes prête.\n$@c{serious_mopen_fists}Surtout ne te retiens pas et donne-moi tout ce que tas !"
},
"victory": {
"1": "@c{shock}Wah… Tu mas vraiment lavé.\nTes vraiment une débutante ?\n$@c{smile}Tas peut-être eu de la chance, mais…\nPeut-être que tarriveras jusquau bout du chemin.\n$Dailleurs, le prof ma demandé de te filer ces objets.\nIls ont lair sympas.\n$@c{serious_smile_fists}Bonne chance à toi !"
@ -560,7 +441,7 @@
},
"rival_6": {
"encounter": {
"1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}Jai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}Cest même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}Jignore si je serai capable de laccomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et cest comme si quelque chose ici me parlait.\n$Comme si cétait tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble semblent si proches ne sont rien de plus quun lointain souvenir.\n$@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça naura jamais de fin et tes la seule à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que cest la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens à pas me battre ici et maintenant, tu nas aucune chance."
"1": "@c{smile_eclosed}Nous y revoilà.\n$@c{neutral}Jai eu du temps pour réfléchir à tout ça.\nIl y a une raison à pourquoi tout semble étrange.\n$@c{neutral_eclosed}Ton rêve, ma volonté de te battre…\nFont partie de quelque chose de plus grand.\n$@c{serious}Cest même pas à propos de moi, ni de toi… Mais du monde, @c{serious_mhalf_fists}et te repousser dans tes limites est ma mission.\n$@c{neutral_eclosed}Jignore si je serai capable de laccomplir, mais je ferai tout ce qui est en mon pouvoir.\n$@c{neutral}Cet endroit est terrifiant… Et pourtant il ma lair familier, comme si jy avais déjà mis les pieds.\n$@c{serious_mhalf_fists}Tu ressens la même chose, pas vrai ?\n$@c{serious}… et cest comme si quelque chose ici me parlait.\n$Comme si cétait tout ce que ce monde avait toujours connu.\n$Ces précieux moments ensemble semblent si proches ne sont rien de plus quun lointain souvenir.\n$@c{neutral_eclosed}Dailleurs, qui peut dire aujourdhui quils ont pu être réels ?\n$@c{serious_mopen_fists}Il faut que tu persévères. Si tu tarrêtes, ça n'aura jamais de fin et tes la seule à en être capable.\n$@c{serious_smile_fists}Difficile de comprendre le sens de tout ça, je sais juste que cest la réalité.\n$@c{serious_mopen_fists}Si tu ne parviens à pas me battre ici et maintenant, tu nas aucune chance."
},
"victory": {
"1": "@c{smile_eclosed}Jai fait ce que javais à faire.\n$Promets-moi juste une chose.\n@c{smile}Après avoir réparé ce monde… Rentre à la maison."
@ -574,4 +455,4 @@
"1": "@c{smile_ehalf}Je… Je crois que jai rempli ma mission…\n$@c{smile_eclosed}Promets-moi… Après avoir réparé ce monde… Reviens à la maison saine et sauve.\n$@c{smile_ehalf}… Merci."
}
}
}
}

View File

@ -38,7 +38,7 @@
"3": "Je te connais pas. Ça te dis de te battre ?",
"4": "Prenons du bon temps avec ce combat Pokémon !",
"5": "Je vais tapprendre à te battre avec tes Pokémon !",
"6": "Un combat doit toujours être pris au sérieux.\nTes prêt à te battre ?",
"6": "Un combat doit être pris au sérieux. Tes prêt à te battre ?",
"7": "Tu seras pas jeune éternellement. Tas quune chance pendant un combat. Bientôt, tu seras plus quun souvenir.",
"8": "Tu ferais mieux dy aller doucement avec moi. Mais je vais me battre sérieusement !",
"9": "Je mennuie à lécole. Ya rien à y faire. *Baille*\nJe me bats juste pour passer le temps."
@ -69,7 +69,7 @@
"defeat": {
"1": "Tu ne devrais pas ténerver sur tes Pokémon, même après une défaite.",
"2": "Alors ? Pas mal mes Pokémon, hein ? Je suis fait pour ça.",
"3": "Peu importe à quel point taimes tes Pokémon, il faut toujours de la discipline sils se comportent mal."
"3": "Peut importe à quel point taimes tes Pokémon, il faut toujours de la discipline sils se comportent mal."
}
},
"breeder_female": {
@ -93,7 +93,7 @@
"encounter": {
"1": "Aaah non ! Javais une touche !\nTu comptes faire quoi pour arranger ça ?",
"2": "Bouge de là ! Tu fais peur aux Pokémon !",
"3": "Voyons si tarrives à ferrer une victoire !"
"3": "Voyons si t'arrives à ferrer une victoire !"
},
"victory": {
"1": "Vas-y là, oublie.",
@ -148,7 +148,7 @@
},
"victory": {
"1": "Très bien… Tas de bons Pokémon…",
"2": "Quoi ?! Mais cest moi le génie des combats !",
"2": "Quoi ?! Mais c'est moi le génie des combats !",
"3": "Évidemment que tes le personnage principal !",
"4": "OK ! OK ! Tu pourrais être un Topdresseur !"
},
@ -170,97 +170,81 @@
"rocket_grunt": {
"encounter": {
"1": "Nous sommes de retour !",
"2": "Ça bosse dur, ici ! Alors du balai !",
"3": "File-nous tes Pokémon ou tu vas gouter à la colère de la Team Rocket !",
"4": "Sois témoin de ce quest une vraie terreur de la Team Rocket!",
"5": "Hé gamin ! Moi être guy member of la Team Rocket !"
"2": "We're pulling a big job here! Get lost, kid!",
"3": "Hand over your Pokémon, or face the wrath of Team Rocket!",
"4": "You're about to experience the true terror of Team Rocket!",
"5": "Hey, kid! Me am a Team Rocket member kind of guy!"
},
"victory": {
"1": "Une fois de plus la Team Rocket senvole vers dautres cieux !",
"2": "Mince! Jai laissé tomber\nla Clé Ascenseur !",
"3": "Jai tout foiré !",
"4": "Mes compagnons vont me venger !",
"5": "Toi dire quoi ? Forget que tu mas vu !\nYou nas rien seen !"
"2": "Oh no! I dropped the Lift Key!",
"3": "I blew it!",
"4": "My associates won't stand for this!",
"5": "You say what? Team Rocket bye-bye a go-go? Broken it is says you?"
}
},
"magma_grunt": {
"encounter": {
"1": "Nespère pas recevoir de la pitié si tu te mets sur le chemin de la Team Magma !",
"2": "Ne te mêle pas de nos affaires ! On va rendre ce monde meilleur !",
"3": "Hors de mon chemin ! La Team Magma na pas de temps pour les gamins !",
"4": "Jespère que tas quelques marshmallows, car ça va chauffer !",
"5": "On va utiliser le puissance dun volcan ! Ça va être… explosif ! Tu las… ? Héhé !"
"2": "You'd better not interfere with our plans! We're making the world a better place!",
"3": "You're in the way! Team Magma has no time for kids like you!",
"4": "I hope you brought marshmallows because things are about to heat up!",
"5": "We're going to use the power of a volcano! It's gonna be... explosive! Get it? Heh heh!"
},
"victory": {
"1": "Je…?\nJai perdu ?!",
"2": "Je peux pas croire que jai pas pris mon déjeuner juste pour ça…",
"3": "Impossible ! Tes quun gosse !",
"4": "Aahhh…\nJaurais dû directement rentrer à la planque…",
"5": "Tu mas démoli… Tu crois que le boss va suspendre mon salaire ?"
"2": "I can't believe I lost! I even skipped lunch for this",
"3": "No way! You're just a kid!",
"4": "Urrrgh... I should've ducked into our hideout right away...",
"5": "You beat me... Do you think the boss will dock my pay for this?"
}
},
"aqua_grunt": {
"encounter": {
"1": "Aucune pitié si tu te mets sur le chemin de la Team Aqua, même pour un gamin !",
"2": "Grrr…\nTu as eu le culot de topposer à la Team Aqua !",
"3": "Je vais te liquéfier !\nEt ce sera pas quà cause des mes Pokémon Eau !",
"4": "Nous, la Team Aqua, existons pour le bien commun !",
"5": "Prépare-toi à te faire emporter par le courant de…\nEuh… Mes Pokémon ! Oui, mes Pokémon !"
"2": "Grrr... You've got some nerve meddling with Team Aqua!",
"3": "You're about to get soaked! And not just from my water Pokémon!",
"4": "We, Team Aqua, exist for the good of all!",
"5": "Prepare to be washed away by the tides of my... uh, Pokémon! Yeah, my Pokémon!"
},
"victory": {
"1": "Comment ça ?",
"2": "Ah, javais pas prévu dêtre gêné par un mouflet qui se mêle de tout !",
"3": "Jai perdu ?! Super, jai plus quà nager jusquà la planque maintenant…",
"4": "Oh non quelle angoisse…\nLe boss va me démonter…",
"5": "Je suis battu… Tu penses que le boss va me faire subir le supplice de la planche ?…"
"2": "Arrgh, I didn't count on being meddled with by some meddling kid!",
"3": "I lost?! Guess I'll have to swim back to the hideout now...",
"4": "Oh, man, what a disaster... The boss is going to be furious...",
"5": "You beat me... Do you think the boss will make me walk the plank for this?"
}
},
"galactic_grunt": {
"encounter": {
"1": "Ne te mets pas en travers de la Team Galaxie !",
"2": "Sois témoin de la puissance de notre technologie et du futur qui se profile !",
"3": "Au nom de la Team Galaxie, jéliminerai quiconque se mettera sur notre route !",
"4": "Prépare ta défaite !",
"5": "Jespère que tes prêt à te prendre une raclée de lespace !"
"2": "Witness the power of our technology and the future we envision!",
"3": "In the name of Team Galactic, I'll eliminate anyone who stands in our way!",
"4": "Get ready to lose!",
"5": "Hope you're ready for a cosmic beatdown!"
},
"victory": {
"1": "Désactivation…",
"2": "Cet échec nest quune poussière face à nos ambitions débordantes.",
"3": "Notre projet est bien plus important que cette défaite.",
"4": "Comment ?!",
"5": "Note à moi-même :\nMentrainer aux combats Pokémon. Ça urge…"
"2": "This setback means nothing in the grand scheme.",
"3": "Our plans are bigger than this defeat.",
"4": "How?!",
"5": "Note to self: practice Pokémon battling, ASAP."
}
},
"plasma_grunt": {
"encounter": {
"1": "Pas de quatiers à ceux qui ne suivent pas notre idéal !",
"2": "Si je gagne, tu relâches tous tes Pokémon !",
"3": "Si tu te mets en travers de la Team Plasma, je moccuperai de toi personnellement !",
"4": "La Team Plasma va libérer les Pokémon de tous les humains égoïstes dans ton genre !",
"5": "Nos coupes sont lunaires… Mais en combat ?\nTu vas vite le découvrir."
"2": "If I win against you, release your Pokémon!",
"3": "If you get in the way of Team Plasma, I'll take care of you!",
"4": "Team Plasma will liberate Pokémon from selfish humans like you!",
"5": "Our hairstyles are out of this world... but our battling skills? You'll find out soon enough."
},
"victory": {
"1": "Plasmaaaaaaaaa !",
"2": "Comment ai-je pu perdre…",
"3": "… Ce Pokémon est nul, jvais aller en voler de meilleurs !",
"4": "Les plans ambitieux connaissent toujours leurs lots dinterruptions.",
"5": "Cest mauvais… MAUVAIS MAUVAIS MAUVAIS MAUVAIS !\nVa falloir battre en retraite, cest la méga cata !"
}
},
"flare_grunt": {
"encounter": {
"1": "Tes Pokémon ne sont pas dignes de lélégance de la Team Flare.",
"2": "Tas des lunettes de soleil jespère ?\nCar prépare-toi à être ébloui !",
"3": "La Team Flare va purifier ce monde de toute imperfection !",
"4": "Prépare-toi à découvrir lindiscutable sens du style de la Team Flare !",
"5": "La mode, cest important !"
},
"victory": {
"1": "Mon futur na pas lair si radieux.",
"2": "Les combats semblent être plus complexes que je le pensais.\nRetour aux planches à dessin.",
"3": "Ehhhh ?! Jai perdu ?!",
"4": "Même dans la défaite, lélégance de la Team Flare continue de rayonner sur ce monde.",
"5": "Jappelle pas ça perdre, jappelle ça échouer avec panache !"
"2": "How could I lose...",
"3": "...What a weak Pokémon, I'll just have to go steal some better ones!",
"4": "Great plans are always interrupted.",
"5": "This is bad... Badbadbadbadbadbadbad! Bad for Team Plasma! Or Plasbad, for short!"
}
},
"rocket_boss_giovanni_1": {
@ -395,77 +379,6 @@
"1": "Les ignorants sans aucune vision nauront donc de cesse de souiller ce monde."
}
},
"brock": {
"encounter": {
"1": "Mon expertise des types Roche va te mettre au sol ! En garde !",
"2": "Tu veux toujours te battre avec moi ? Même en sachant que tu vas perdre ?",
"3": "Laisse-moi de montrer la véritable force de mes Pokémon Roche !"
},
"victory": {
"1": "Jétais trop sûr de moi, cest pour ça que jai perdu.",
"2": "Ce monde est vaste ! Je suis honoré davoir pu taffronter.",
"3": "Peut-être bien que je naurais pas dû abandonner ma vocation dÉleveur…"
},
"defeat": {
"1": "La défense est la meilleure des attaques !\nTelle est ma méthode !",
"2": "Viens étudier des roches avec moi la prochaine fois si tu veux apprendre à mieux les aborder !",
"3": "Tout ce temps à voyager autour du monde paie enfin !"
}
},
"misty": {
"encounter": {
"1": "Ma tactique ? Attaquer avec des Pokémon Eau !",
"2": "Je vais te prouver le tsunami que sont mes Pokémon aquatiques !",
"3": "Mon rêve, cétait de voyager et de défier des Dresseurs super forts. Seras-tu à la hauteur ?"
},
"victory": {
"1": "OK. Tes pas naze… Je le reconnais…",
"2": "Pfff… Tas juste eu de la chance hein ?!",
"3": "Ouah ! Tes super balèze !"
},
"defeat": {
"1": "Quen dis-tu? Cest ça, la puissance des Pokémon Eau !",
"2": "Jespère que tas pris note des élégantes techniques de nage de mes Pokémon !",
"3": "Tes Pokémon ne jouent visiblement pas dans le même bassin…"
}
},
"lt_surge": {
"encounter": {
"1": "Tas pas froid aux yeux, soldat ! Les combats Pokémon, cest la guerre !",
"2": "Tu as du guts pour venir me fight ici ! Je vais te shock !",
"3": "Compte tes dents, tu vas morfler !\nMes Pokémon Électrik vont tatomiser !"
},
"victory": {
"1": "Whoo ! Tiras loin toi.",
"2": "Oh noes ! Mes tricks électriques sont à plat…\nYou are very fortiche!",
"3": "Tu es very costaud ! Je vais training very dur mes Pokémon, moi too, et on sera Number One !"
},
"defeat": {
"1": "Oh yeah !\nMes Pokémon Électrik sont les best du monde !",
"2": "Oh yeah, baby ! I am trop fort !",
"3": "Une combat Pokémon, cest comme une guerre et tas eu droit à une bataille de premier ordre !"
}
},
"erika": {
"encounter": {
"1": "Il fait beau, aujourdhui, nest-ce pas… ?\nQuoi un combat… ? Très bien…",
"2": "Larrangement floral est ma spécialité, et mes Pokémon sont de type Plante. Quoi ? Tu veux te battre ?",
"3": "Il fait beau… Le soleil brille… Les plantes bourgeonnent… Je mennuie…",
"4": "Voir un tel jardin rempli de fleurs est si apaisant…"
},
"victory": {
"1": "Bien joué, cest mértié.",
"2": "Dommage, on samusait si bien…",
"3": "Oh non, le combat est terminé…",
"4": "Aaah, ça fait du bien !\nMerci, jen avais besoin."
},
"defeat": {
"1": "Jai failli mendormir…",
"2": "Oh non… Mes Pokémon Plante ont lair de tavoir bien endormi…",
"3": "Ce combat était si apaisant…",
"4": "Oh non… Cest tout ?"
}
},
"alder": {
"encounter": {
"1": "Prépare-toi pour un combat contre le meilleur Dresseur dUnys !"
@ -498,7 +411,7 @@
},
"rival_female": {
"encounter": {
"1": "@c{smile_wave}Ah, te voilà ! Je tai cherché partout !\n@c{angry_mopen}On oublie de dire au revoir à sa meilleure amie ?\n$@c{smile_ehalf}Tas décidé de réaliser ton rêve, hein ?\nCe jour est donc vraiment arrivé…\n$@c{smile}Je veux bien te pardonner de mavoir oubliée,\nà une conditon. @c{smile_wave_wink}Que tu maffronte !\n$@c{angry_mopen}Donne tout ! Ce serait dommage que ton aventure finisse avant davoir commencé, hein ?"
"1": "@c{smile_wave}Ah, je te cherchais ! Je tai cherché partout !\n@c{angry_mopen}On oublie de dire au revoir à sa meilleure amie ?\n$@c{smile_ehalf}Tas décidé de réaliser ton rêve, hein ?\nCe jour est donc vraiment arrivé…\n$@c{smile}Je veux bien te pardonner de mavoir oubliée,\nà une conditon. @c{smile_wave_wink}Que tu maffronte !\n$@c{angry_mopen}Donne tout ! Ce serait dommage que ton aventure finisse avant davoir commencé, hein ?"
},
"victory": {
"1": "@c{shock}Tu viens de commencer et tes déjà si fort ?!@d{96}\n@c{angry}Tas triché non ? Avoue !\n$@c{smile_wave_wink}Jdéconne !@d{64} @c{smile_eclosed}Jai perdu dans les règles…\nJai le sentiment que tu vas très bien ten sortir.\n$@c{smile}Dailleurs, le prof veut que je te donne ces quelques objets. Ils te seront utiles, pour sûr !\n$@c{smile_wave}Fais de ton mieux, comme toujours !\nJe crois fort en toi !"
@ -596,4 +509,4 @@
"1": "@c{smile_ehalf}Je… Je crois que jai rempli ma mission…\n$@c{smile_eclosed}Promets-moi… Après avoir réparé ce monde… Reviens à la maison sain et sauf.\n$@c{smile_ehalf}… Merci."
}
}
}
}

View File

@ -4,23 +4,23 @@
"ultraTier": "Épique",
"masterTier": "Légendaire",
"defaultTier": "Commun",
"hatchWavesMessageSoon": "Il fait du bruit. Il va éclore !",
"hatchWavesMessageSoon": "Il fait du bruit. Il va éclore !",
"hatchWavesMessageClose": "Il bouge de temps en temps. Il devrait bientôt éclore.",
"hatchWavesMessageNotClose": "Quest-ce qui va en sortir ? Ça va mettre du temps.",
"hatchWavesMessageLongTime": "Cet Œuf va surement mettre du temps à éclore.",
"hatchWavesMessageLongTime": "Cet Œuf va sûrement mettre du temps à éclore.",
"gachaTypeLegendary": "Taux de Légendaires élevé",
"gachaTypeMove": "Taux de Capacité Œuf Rare élevé",
"gachaTypeShiny": "Taux de Chromatiques élevé",
"selectMachine": "Sélectionnez une machine.",
"notEnoughVouchers": "Vous navez pas assez de coupons !",
"tooManyEggs": "Vous avez trop dŒufs !",
"notEnoughVouchers": "Vous navez pas assez de coupons !",
"tooManyEggs": "Vous avez trop dŒufs !",
"pull": "Tirage",
"pulls": "Tirages",
"sameSpeciesEgg": "{{species}} sortira de cet Œuf !",
"hatchFromTheEgg": "{{pokemonName}} sort de lŒuf !",
"hatchFromTheEgg": "{{pokemonName}} sort de lŒuf !",
"eggMoveUnlock": "Capacité Œuf débloquée :\n{{moveName}}",
"rareEggMoveUnlock": "Capacité Œuf Rare débloquée :\n{{moveName}}",
"moveUPGacha": "Bonus Capacité\nŒuf Rare !",
"shinyUPGacha": "Bonus\nChromatique !",
"legendaryUPGacha": "Bonus !"
}
"moveUPGacha": "Bonus Capacité\nŒuf Rare !",
"shinyUPGacha": "Bonus\nChromatique !",
"legendaryUPGacha": "Bonus !"
}

View File

@ -42,14 +42,14 @@
"wave": "Vague",
"loading": "Chargement…",
"loadingAsset": "Chargement de la ressource : {{assetName}}",
"playersOnline": "Joueurs connectés",
"playersOnline": "Joueurs Connectés",
"yes": "Oui",
"no": "Non",
"disclaimer": "AVERTISSEMENT",
"disclaimerDescription": "Ce jeu nest pas un produit fini et peut contenir des problèmes de jouabilité, dont de possibles pertes de sauvegardes,\ndes modifications sans avertissement et pourrait ou non encore être mis à jour ou terminé.",
"choosePokemon": "Sélectionnez un Pokémon.",
"renamePokemon": "Renommer le Pokémon",
"renamePokemon": "Renommer Pokémon",
"rename": "Renommer",
"nickname": "Surnom",
"errorServerDown": "Oupsi ! Un problème de connexion au serveur est survenu.\n\nVous pouvez garder cette fenêtre ouverte,\nle jeu se reconnectera automatiquement."
}
}

View File

@ -11,7 +11,7 @@
"PokemonHeldItemModifierType": {
"extra": {
"inoperable": "{{pokemonName}} ne peut pas\nporter cet objet !",
"tooMany": "{{pokemonName}} porte trop\ndexemplaires de cet objet !"
"tooMany": "{{pokemonName}} possède trop\ndexemplaires de cet objet !"
}
},
"PokemonHpRestoreModifierType": {
@ -108,7 +108,7 @@
"description": "Permet à certains Pokémon de changer de forme."
},
"FusePokemonModifierType": {
"description": "Fusionne deux Pokémon (transfère le talent, sépare les stats de base et les types, partage les capacités)."
"description": "Fusionne deux Pokémon (transfère le talent, sépare les stats de base et les types, partage le movepool)."
},
"TerastallizeModifierType": {
"name": "Téra-Éclat {{teraType}}",
@ -194,7 +194,7 @@
"RELIC_GOLD": { "name": "Vieux Ducat" },
"AMULET_COIN": { "name": "Pièce Rune", "description": "Augmente de 20% les gains dargent." },
"GOLDEN_PUNCH": { "name": "Poing Doré", "description": "La moitié des dégâts infligés sont convertis en argent." },
"GOLDEN_PUNCH": { "name": "Poing Doré", "description": "50% des dégâts infligés sont convertis en argent." },
"COIN_CASE": { "name": "Boite Jetons", "description": "Tous les 10 combats, recevez 10% de votre argent en intérêts." },
"LOCK_CAPSULE": { "name": "Poké Écrin", "description": "Permet de conserver la rareté des objets si vous relancez les objets proposés." },
@ -205,13 +205,13 @@
"MULTI_LENS": { "name": "Lentille Multi" },
"HEALING_CHARM": { "name": "Charme Soin", "description": "Augmente de 10% lefficacité des capacités et objets de soin de PV (hors Rappels)." },
"CANDY_JAR": { "name": "Bonbonnière", "description": "Augmente de 1 le nombre de niveaux gagnés à lutilisation dun Super Bonbon ou dun Hyper Bonbon." },
"CANDY_JAR": { "name": "Bonbonnière", "description": "Augmente de 1 le nombre de niveaux gagnés à lutilisation dun Super Bonbon." },
"BERRY_POUCH": { "name": "Sac à Baies", "description": "Ajoute 30% de chances quune Baie utilisée ne soit pas consommée." },
"FOCUS_BAND": { "name": "Bandeau", "description": "Ajoute 10% de chances de survivre avec 1 PV si les dégâts reçus pouvaient mettre K.O. ." },
"QUICK_CLAW": { "name": "Vive Griffe", "description": "Ajoute 10% de chances dagir en premier, indépendamment de la Vitesse (après la priorité)." },
"QUICK_CLAW": { "name": "Vive Griffe", "description": "Ajoute 10% de chances dagir en premier, indépendamment de la vitesse (après la priorité)." },
"KINGS_ROCK": { "name": "Roche Royale", "description": "Ajoute 10% de chances quune capacité offensive apeure ladversaire." },
@ -261,14 +261,14 @@
},
"TempBattleStatBoosterStatName": {
"ATK": "lAttaque",
"DEF": "la Défense",
"SPATK": "lAtq. Spé.",
"SPDEF": "la Déf. Spé.",
"SPD": "la Vitesse",
"ACC": "la précision",
"CRIT": "le taux de critique",
"EVA": "lesquive",
"ATK": "Attaque",
"DEF": "Défense",
"SPATK": "Atq. Spé.",
"SPDEF": "Déf. Spé.",
"SPD": "Vitesse",
"ACC": "Précision",
"CRIT": "Taux de critique",
"EVA": "Esquive",
"DEFAULT": "???"
},
@ -452,4 +452,4 @@
"FAIRY_MEMORY": "ROM Fée",
"BLANK_MEMORY": "ROM Vierge"
}
}
}

View File

@ -3,10 +3,10 @@
"turnHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par les {{typeName}} !",
"hitHealApply": "Les PV de {{pokemonNameWithAffix}}\nsont un peu restaurés par le {{typeName}} !",
"pokemonInstantReviveApply": "{{pokemonNameWithAffix}} a repris connaissance\navec sa {{typeName}} et est prêt à se battre de nouveau !",
"pokemonResetNegativeStatStageApply": "Les stats baissées de {{pokemonNameWithAffix}}\nsont restaurées par l{{typeName}} !",
"pokemonResetNegativeStatStageApply": "{{pokemonNameWithAffix}}'s lowered stats were restored\nby its {{typeName}}!",
"moneyInterestApply": "La {{typeName}} vous rapporte\n{{moneyAmount}}  dintérêts !",
"turnHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est absorbé·e\npar le {{typeName}} de {{pokemonName}} !",
"contactHeldItemTransferApply": "{{itemName}} de {{pokemonNameWithAffix}} est volé·e\npar l{{typeName}} de {{pokemonName}} !",
"enemyTurnHealApply": "{{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
"bypassSpeedChanceApply": "{{itemName}} de {{pokemonName}}\nlui permet dagir plus vite que dhabitude!"
}
}

View File

@ -25,7 +25,7 @@
},
"firePunch": {
"name": "Poing Feu",
"effect": "Un coup de poing enflammé vient frapper la cible, ce qui peut la bruler (10% de chances)."
"effect": "Un coup de poing enflammé vient frapper la cible, ce qui peut la brûler (10% de chances)."
},
"icePunch": {
"name": "Poing Glace",
@ -205,11 +205,11 @@
},
"ember": {
"name": "Flammèche",
"effect": "La cible est attaquée par une faible flamme qui peut aussi la bruler."
"effect": "La cible est attaquée par une faible flamme qui peut aussi la brûler."
},
"flamethrower": {
"name": "Lance-Flammes",
"effect": "La cible reçoit un torrent de flammes qui peut aussi la bruler (10% de chances)."
"effect": "La cible reçoit un torrent de flammes qui peut aussi la brûler (10% de chances)."
},
"mist": {
"name": "Brume",
@ -356,7 +356,7 @@
"effect": "Le lanceur provoque un tremblement de terre touchant tous les Pokémon autour de lui."
},
"fissure": {
"name": "Abime",
"name": "Abîme",
"effect": "Le lanceur fait tomber la cible dans une crevasse. Si cette attaque réussit, elle met K.O. sur le coup."
},
"dig": {
@ -489,7 +489,7 @@
},
"smog": {
"name": "Purédpois",
"effect": "Le lanceur attaque à laide dune éruption de gaz répugnants qui peuvent aussi empoisonner la cible."
"effect": "Le lanceur attaque à l'aide d'une éruption de gaz répugnants qui peuvent aussi empoisonner la cible."
},
"sludge": {
"name": "Détritus",
@ -501,7 +501,7 @@
},
"fireBlast": {
"name": "Déflagration",
"effect": "Un déluge de flammes ardentes submerge la cible, ce qui peut aussi la bruler (10% de chances)."
"effect": "Un déluge de flammes ardentes submerge la cible, ce qui peut aussi la brûler (10% de chances)."
},
"waterfall": {
"name": "Cascade",
@ -581,7 +581,7 @@
},
"dizzyPunch": {
"name": "Uppercut",
"effect": "Un enchainement de coups de poing cadencés frappe lennemi. Peut aussi le rendre confus."
"effect": "Un enchaînement de coups de poing cadencés frappe lennemi. Peut aussi le rendre confus."
},
"spore": {
"name": "Spore",
@ -632,7 +632,7 @@
"effect": "Le lanceur mord lennemi à laide de ses incisives aiguisées. Peut aussi lapeurer (10% de chances)."
},
"sharpen": {
"name": "Affutage",
"name": "Affûtage",
"effect": "Le lanceur réduit son nombre de polygones pour accentuer ses angles et augmenter son Attaque."
},
"conversion": {
@ -641,7 +641,7 @@
},
"triAttack": {
"name": "Triplattaque",
"effect": "Le lanceur envoie trois boules dénergie simultanément qui peuvent aussi paralyser, bruler ou geler la cible (6.67% de chances)."
"effect": "Le lanceur envoie trois boules dénergie simultanément qui peuvent aussi paralyser, brûler ou geler la cible (6.67% de chances)."
},
"superFang": {
"name": "Croc Fatal",
@ -661,7 +661,7 @@
},
"sketch": {
"name": "Gribouille",
"effect": "Le lanceur apprend la dernière capacité utilisée par la cible. Gribouille disparait après utilisation."
"effect": "Le lanceur apprend la dernière capacité utilisée par la cible. Gribouille disparaît après utilisation."
},
"tripleKick": {
"name": "Triple Pied",
@ -685,7 +685,7 @@
},
"flameWheel": {
"name": "Roue de Feu",
"effect": "Le lanceur sentoure de feu et charge la cible, ce qui peut aussi la bruler (10% de chances)."
"effect": "Le lanceur sentoure de feu et charge la cible, ce qui peut aussi la brûler (10% de chances)."
},
"snore": {
"name": "Ronflement",
@ -881,7 +881,7 @@
},
"sacredFire": {
"name": "Feu Sacré",
"effect": "Le lanceur génère un feu mystique dune intensité redoutable pour attaquer lennemi. Peut aussi le bruler (50% de chances)."
"effect": "Le lanceur génère un feu mystique dune intensité redoutable pour attaquer lennemi. Peut aussi le brûler (50% de chances)."
},
"magnitude": {
"name": "Ampleur",
@ -1025,7 +1025,7 @@
},
"heatWave": {
"name": "Canicule",
"effect": "Le lanceur provoque une vague de chaleur qui peut aussi bruler la cible (10% de chances)."
"effect": "Le lanceur provoque une vague de chaleur qui peut aussi brûler la cible (10% de chances)."
},
"hail": {
"name": "Grêle",
@ -1041,7 +1041,7 @@
},
"willOWisp": {
"name": "Feu Follet",
"effect": "Le lanceur projette des flammes maléfiques à la cible pour lui infliger une brulure."
"effect": "Le lanceur projette des flammes maléfiques à la cible pour lui infliger une brûlure."
},
"memento": {
"name": "Souvenir",
@ -1049,7 +1049,7 @@
},
"facade": {
"name": "Façade",
"effect": "Une capacité dont la puissance double lorsque le lanceur est empoisonné, paralysé ou brulé."
"effect": "Une capacité dont la puissance double lorsque le lanceur est empoisonné, paralysé ou brûlé."
},
"focusPunch": {
"name": "Mitra-Poing",
@ -1145,7 +1145,7 @@
},
"refresh": {
"name": "Régénération",
"effect": "Le lanceur se repose pour guérir dun empoisonnement, dune brulure ou dune paralysie."
"effect": "Le lanceur se repose pour guérir dun empoisonnement, dune brûlure ou dune paralysie."
},
"grudge": {
"name": "Rancune",
@ -1192,8 +1192,8 @@
"effect": "Danse qui rend confus tous les Pokémon autour du lanceur."
},
"blazeKick": {
"name": "Pied Bruleur",
"effect": "Le lanceur envoie un coup de pied au taux de critiques élevé. Peut aussi bruler la cible (10% de chances)."
"name": "Pied Brûleur",
"effect": "Le lanceur envoie un coup de pied au taux de critiques élevé. Peut aussi brûler la cible (10% de chances)."
},
"mudSport": {
"name": "Lance-Boue",
@ -1573,7 +1573,7 @@
},
"flareBlitz": {
"name": "Boutefeu",
"effect": "Le lanceur sembrase avant de charger la cible, ce qui peut la bruler (10% de chances). Le choc blesse aussi gravement le lanceur."
"effect": "Le lanceur sembrase avant de charger la cible, ce qui peut la brûler (10% de chances). Le choc blesse aussi gravement le lanceur."
},
"forcePalm": {
"name": "Forte-Paume",
@ -1693,7 +1693,7 @@
},
"fireFang": {
"name": "Crocs Feu",
"effect": "Le lanceur utilise une morsure enflammée qui peut aussi bruler (10% de chances) ou apeurer (10% de chances) la cible."
"effect": "Le lanceur utilise une morsure enflammée qui peut aussi brûler (10% de chances) ou apeurer (10% de chances) la cible."
},
"shadowSneak": {
"name": "Ombre Portée",
@ -1741,7 +1741,7 @@
},
"lavaPlume": {
"name": "Ébullilave",
"effect": "Des flammes sabattent sur tous les Pokémon autour du lanceur, ce qui peut aussi les bruler (10% de chances)."
"effect": "Des flammes sabattent sur tous les Pokémon autour du lanceur, ce qui peut aussi les brûler (10% de chances)."
},
"leafStorm": {
"name": "Tempête Verte",
@ -1796,7 +1796,7 @@
"effect": "Le lanceur libère une myriade de rayons de lumière. Le type varie selon la plaque que tient le lanceur."
},
"bugBite": {
"name": "Piqure",
"name": "Piqûre",
"effect": "Le lanceur pique la cible. Si celle-ci tient une Baie, le lanceur la dévore et obtient son effet."
},
"chargeBeam": {
@ -1865,7 +1865,7 @@
},
"shadowForce": {
"name": "Revenant",
"effect": "Le lanceur disparait au premier tour et frappe la cible au deuxième. Cette capacité fonctionne même si la cible se protège."
"effect": "Le lanceur disparaît au premier tour et frappe la cible au deuxième. Cette capacité fonctionne même si la cible se protège."
},
"honeClaws": {
"name": "Aiguisage",
@ -2009,7 +2009,7 @@
},
"scald": {
"name": "Ébullition",
"effect": "Le lanceur projette un jet deau bouillante sur la cible, ce qui peut aussi la bruler (30% de chances)."
"effect": "Le lanceur projette un jet deau bouillante sur la cible, ce qui peut aussi la brûler (30% de chances)."
},
"shellSmash": {
"name": "Exuviation",
@ -2037,7 +2037,7 @@
},
"incinerate": {
"name": "Calcination",
"effect": "Des flammes calcinent la cible. Si elle tient un objet, une Baie par exemple, celui-ci est brulé et devient inutilisable."
"effect": "Des flammes calcinent la cible. Si elle tient un objet, une Baie par exemple, celui-ci est brûlé et devient inutilisable."
},
"quash": {
"name": "À la Queue",
@ -2065,19 +2065,19 @@
},
"inferno": {
"name": "Feu dEnfer",
"effect": "La cible est entourée dun torrent de flammes ardentes qui la brulent."
"effect": "La cible est entourée dun torrent de flammes ardentes qui la brûlent."
},
"waterPledge": {
"name": "Aire dEau",
"effect": "Une masse deau sabat sur la cible. Si cette capacité est utilisée en même temps quAire de Feu, la puissance augmente et un arc-en-ciel apparait."
"effect": "Une masse deau sabat sur la cible. Si cette capacité est utilisée en même temps quAire de Feu, la puissance augmente et un arc-en-ciel apparaît."
},
"firePledge": {
"name": "Aire de Feu",
"effect": "Une masse de feu sabat sur la cible. Si cette capacité est utilisée en même temps quAire dHerbe, la puissance augmente et une mer de feu apparait."
"effect": "Une masse de feu sabat sur la cible. Si cette capacité est utilisée en même temps quAire dHerbe, la puissance augmente et une mer de feu apparaît."
},
"grassPledge": {
"name": "Aire dHerbe",
"effect": "Une masse végétale sabat sur la cible. Si cette capacité est utilisée en même temps quAire dEau, la puissance augmente et un marécage apparait."
"effect": "Une masse végétale sabat sur la cible. Si cette capacité est utilisée en même temps quAire dEau, la puissance augmente et un marécage apparaît."
},
"voltSwitch": {
"name": "Change Éclair",
@ -2177,7 +2177,7 @@
},
"searingShot": {
"name": "Incendie",
"effect": "Des boules de feu sabattent sur tous les Pokémon autour du lanceur. Peut aussi les bruler (30% de chances)."
"effect": "Des boules de feu sabattent sur tous les Pokémon autour du lanceur. Peut aussi les brûler (30% de chances)."
},
"technoBlast": {
"name": "Techno-Buster",
@ -2201,7 +2201,7 @@
},
"blueFlare": {
"name": "Flamme Bleue",
"effect": "De magnifiques et redoutables flammes bleues fondent sur lennemi. Peut aussi le bruler (20% de chances)."
"effect": "De magnifiques et redoutables flammes bleues fondent sur lennemi. Peut aussi le brûler (20% de chances)."
},
"fieryDance": {
"name": "Danse du Feu",
@ -2213,7 +2213,7 @@
},
"iceBurn": {
"name": "Feu Glacé",
"effect": "Au second tour, le lanceur projette un souffle de vent glacial dévastateur sur lennemi. Peut aussi le bruler (30% de chances)."
"effect": "Au second tour, le lanceur projette un souffle de vent glacial dévastateur sur lennemi. Peut aussi le brûler (30% de chances)."
},
"snarl": {
"name": "Aboiement",
@ -2261,7 +2261,7 @@
},
"phantomForce": {
"name": "Hantise",
"effect": "Le lanceur disparait au premier tour et frappe au second. Cette attaque passe outre les protections."
"effect": "Le lanceur disparaît au premier tour et frappe au second. Cette attaque passe outre les protections."
},
"trickOrTreat": {
"name": "Halloween",
@ -2333,7 +2333,7 @@
},
"fairyWind": {
"name": "Vent Féérique",
"effect": "Le lanceur déchaine un vent magique qui cingle la cible."
"effect": "Le lanceur déchaîne un vent magique qui cingle la cible."
},
"moonblast": {
"name": "Pouvoir Lunaire",
@ -2345,7 +2345,7 @@
},
"fairyLock": {
"name": "Verrou Enchanté",
"effect": "Des chaines entourent la zone de combat, empêchant tous les Pokémon de quitter le terrain au tour suivant."
"effect": "Des chaînes entourent la zone de combat, empêchant tous les Pokémon de quitter le terrain au tour suivant."
},
"kingsShield": {
"name": "Bouclier Royal",
@ -2365,7 +2365,7 @@
},
"steamEruption": {
"name": "Jet de Vapeur",
"effect": "Le lanceur projette de la vapeur extrêmement chaude sur la cible, ce qui peut aussi la bruler (30% de chances)."
"effect": "Le lanceur projette de la vapeur extrêmement chaude sur la cible, ce qui peut aussi la brûler (30% de chances)."
},
"hyperspaceHole": {
"name": "TrouDimensionnel",
@ -2377,7 +2377,7 @@
},
"mysticalFire": {
"name": "Feu Ensorcelé",
"effect": "Le lanceur attaque en soufflant des flammes brulantes par la bouche et diminue lAttaque Spéciale de la cible."
"effect": "Le lanceur attaque en soufflant des flammes brûlantes par la bouche et diminue lAttaque Spéciale de la cible."
},
"spikyShield": {
"name": "Pico-Défense",
@ -2517,7 +2517,7 @@
},
"tectonicRagePhysical": {
"name": "Éruption Géo-Sismique",
"effect": "Le Pokémon utilise la Force Z pour entrainer ladversaire dans les profondeurs de la terre. La puissance varie selon celle de la capacité originale."
"effect": "Le Pokémon utilise la Force Z pour entraîner ladversaire dans les profondeurs de la terre. La puissance varie selon celle de la capacité originale."
},
"tectonicRageSpecial": {
"name": "Éruption Géo-Sismique",
@ -2653,7 +2653,7 @@
},
"sparklingAria": {
"name": "Aria de lÉcume",
"effect": "Le lanceur émet plusieurs bulles en chantant. Soigne les brulures des Pokémon touchés par ces bulles."
"effect": "Le lanceur émet plusieurs bulles en chantant. Soigne les brûlures des Pokémon touchés par ces bulles."
},
"iceHammer": {
"name": "Marteau de Glace",
@ -2757,7 +2757,7 @@
},
"beakBlast": {
"name": "Bec-Canon",
"effect": "Le lanceur fait chauffer son bec avant dattaquer. Sil subit une attaque directe pendant la montée en température, lattaquant sera brulé."
"effect": "Le lanceur fait chauffer son bec avant dattaquer. Sil subit une attaque directe pendant la montée en température, lattaquant sera brûlé."
},
"clangingScales": {
"name": "Vibrécaille",
@ -2789,7 +2789,7 @@
},
"guardianOfAlola": {
"name": "Colère du Gardien dAlola",
"effect": "Le Pokémon Tutélaire utilise la Force Z et déchaine toute la puissance dAlola sur sa cible. Inflige des dégâts en fonction des PV restants de celle-ci."
"effect": "Le Pokémon Tutélaire utilise la Force Z et déchaîne toute la puissance dAlola sur sa cible. Inflige des dégâts en fonction des PV restants de celle-ci."
},
"soulStealing7StarStrike": {
"name": "Fauche-Âme des Sept Étoiles",
@ -2865,7 +2865,7 @@
},
"naturesMadness": {
"name": "Ire de la Nature",
"effect": "Le lanceur déchaine toute la colère de la nature pour baisser les PV de la cible de moitié."
"effect": "Le lanceur déchaîne toute la colère de la nature pour baisser les PV de la cible de moitié."
},
"multiAttack": {
"name": "Coup Varia-Type",
@ -2873,7 +2873,7 @@
},
"tenMillionVoltThunderbolt": {
"name": "Giga-Tonnerre",
"effect": "Le Pikachu à casquette utilise la Force Z pour augmenter sa puissance électrique avant de la déchainer sur la cible. Taux de critique élevé."
"effect": "Le Pikachu à casquette utilise la Force Z pour augmenter sa puissance électrique avant de la déchaîner sur la cible. Taux de critique élevé."
},
"mindBlown": {
"name": "Caboche-Kaboum",
@ -2893,11 +2893,11 @@
},
"searingSunrazeSmash": {
"name": "Hélio-Choc Dévastateur",
"effect": "Baigné dans la Force Z, Solgaleo attaque en déchainant toute sa puissance. Ignore le talent de la cible."
"effect": "Baigné dans la Force Z, Solgaleo attaque en déchaînant toute sa puissance. Ignore le talent de la cible."
},
"menacingMoonrazeMaelstrom": {
"name": "Rayons Séléno-Explosifs",
"effect": "Baigné dans la Force Z, Lunala attaque en déchainant toute sa puissance. Ignore le talent de la cible."
"effect": "Baigné dans la Force Z, Lunala attaque en déchaînant toute sa puissance. Ignore le talent de la cible."
},
"letsSnuggleForever": {
"name": "Patati-Patattrape",
@ -2913,7 +2913,7 @@
},
"zippyZap": {
"name": "Pika-Sprint",
"effect": "Une attaque électrique rapide comme léclair qui inflige un coup critique à coup sûr. Frappe en priorité."
"effect": "Une attaque électrique rapide comme léclair qui augmente lesquive. Frappe en priorité."
},
"splishySplash": {
"name": "Pika-Splash",
@ -2937,7 +2937,7 @@
},
"sizzlySlide": {
"name": "Évo-Flambo",
"effect": "Évoli sembrase et percure violemment ladversaire. Brule aussi lennemi."
"effect": "Évoli sembrase et percure violemment ladversaire. Brûle aussi lennemi."
},
"glitzyGlow": {
"name": "Évo-Psycho",
@ -2961,7 +2961,7 @@
},
"veeveeVolley": {
"name": "Évo-Chardasso",
"effect": "Le lanceur lance une attaque dès lors quun signe apparait sur le terrain. Les dégâts infligés sont proportionnels à laffection de votre Pokémon"
"effect": "Le lanceur lance une attaque dès lors quun signe apparaît sur le terrain. Les dégâts infligés sont proportionnels à laffection de votre Pokémon"
},
"doubleIronBash": {
"name": "Écrous dPoing",
@ -3005,7 +3005,7 @@
},
"teatime": {
"name": "Thérémonie",
"effect": "Le lanceur invite tous les Pokémon sur le terrain à prendre le gouter autour dune tasse de thé. Ceux qui tiennent une Baie la mangent."
"effect": "Le lanceur invite tous les Pokémon sur le terrain à prendre le goûter autour dune tasse de thé. Ceux qui tiennent une Baie la mangent."
},
"octolock": {
"name": "Octoprise",
@ -3105,7 +3105,7 @@
},
"decorate": {
"name": "Nappage",
"effect": "Augmente fortement lAttaque et lAttaque Spéciale de la cible."
"effect": "Augmente fortement lAttaque et lAttaque Spéciale du lanceur."
},
"drumBeating": {
"name": "Tambour Battant",
@ -3116,8 +3116,8 @@
"effect": "Bloque lennemi pendant 4 à 5 tours."
},
"pyroBall": {
"name": "Ballon Brulant",
"effect": "Le lanceur attaque avec un ballon fait à partir dun caillou enflammé. Peut aussi bruler la cible (10% de chances)."
"name": "Ballon Brûlant",
"effect": "Le lanceur attaque avec un ballon fait à partir dun caillou enflammé. Peut aussi brûler la cible (10% de chances)."
},
"behemothBlade": {
"name": "Gladius Maximus",
@ -3189,7 +3189,7 @@
},
"steelRoller": {
"name": "Métalliroue",
"effect": "Une attaque qui inflige des dégâts et fait disparaitre le champ actif, mais qui échoue sil ny en a pas à ce moment."
"effect": "Une attaque qui inflige des dégâts et fait disparaître le champ actif, mais qui échoue sil ny en a pas à ce moment."
},
"scaleShot": {
"name": "Rafale Écailles",
@ -3225,7 +3225,7 @@
},
"burningJealousy": {
"name": "Feu Envieux",
"effect": "Le lanceur attaque sa cible avec toute sa jalousie. Cette capacité brule tout Pokémon dont les stats ont augmenté pendant ce tour."
"effect": "Le lanceur attaque sa cible avec toute sa jalousie. Cette capacité brûle tout Pokémon dont les stats ont augmenté pendant ce tour."
},
"lashOut": {
"name": "Cent Rancunes",
@ -3257,7 +3257,7 @@
},
"scorchingSands": {
"name": "Sable Ardent",
"effect": "Le lanceur projette du sable chauffé à blanc sur la cible, ce qui peut aussi la bruler (30% de chances)."
"effect": "Le lanceur projette du sable chauffé à blanc sur la cible, ce qui peut aussi la brûler (30% de chances)."
},
"jungleHealing": {
"name": "Selve Salvatrice",
@ -3265,11 +3265,11 @@
},
"wickedBlow": {
"name": "Poing Obscur",
"effect": "Le lanceur assène un coup puissant à la cible. Cette technique qui inflige toujours un coup critique est réservée à ceux qui maitrisent la puissance des Ténèbres."
"effect": "Le lanceur assène un coup puissant à la cible. Cette technique qui inflige toujours un coup critique est réservée à ceux qui maîtrisent la puissance des Ténèbres."
},
"surgingStrikes": {
"name": "Torrent de Coups",
"effect": "Le lanceur assène trois coups fluides à la cible. Cette technique qui inflige toujours un coup critique est réservée à ceux qui maitrisent la puissance de lEau."
"effect": "Le lanceur assène trois coups fluides à la cible. Cette technique qui inflige toujours un coup critique est réservée à ceux qui maîtrisent la puissance de lEau."
},
"thunderCage": {
"name": "Voltageôle",
@ -3285,7 +3285,7 @@
},
"fieryWrath": {
"name": "Fureur Ardente",
"effect": "Le lanceur canalise sa colère et la transforme en émanation brulante, avec laquelle il attaque la cible, ce qui peut aussi apeurer celle-ci (20% de chances)."
"effect": "Le lanceur canalise sa colère et la transforme en émanation brûlante, avec laquelle il attaque la cible, ce qui peut aussi apeurer celle-ci (20% de chances)."
},
"thunderousKick": {
"name": "Coup Fulgurant",
@ -3329,7 +3329,7 @@
},
"ragingFury": {
"name": "Grand Courroux",
"effect": "Le lanceur se déchaine et attaque en projetant de violentes flammes pendant deux ou trois tours. Il devient ensuite confus."
"effect": "Le lanceur se déchaîne et attaque en projetant de violentes flammes pendant deux ou trois tours. Il devient ensuite confus."
},
"waveCrash": {
"name": "Aquatacle",
@ -3373,7 +3373,7 @@
},
"infernalParade": {
"name": "Cortège Funèbre",
"effect": "Une multitude de boules de feu frappent la cible, ce qui peut aussi la bruler (30% de chances et 50% en Style Puissant). La puissance est doublée si celle-ci souffre dune altération de statut."
"effect": "Une multitude de boules de feu frappent la cible, ce qui peut aussi la brûler (30% de chances et 50% en Style Puissant). La puissance est doublée si celle-ci souffre dune altération de statut."
},
"ceaselessEdge": {
"name": "Vagues à Lames",
@ -3389,7 +3389,7 @@
},
"sandsearStorm": {
"name": "Typhon Pyrosable",
"effect": "Le lanceur déclenche un violent typhon mêlé à du sable ardent qui sabat sur la cible, ce qui peut la bruler (30% de chances et 50% en Style Puissant)."
"effect": "Le lanceur déclenche un violent typhon mêlé à du sable ardent qui sabat sur la cible, ce qui peut la brûler (30% de chances et 50% en Style Puissant)."
},
"lunarBlessing": {
"name": "Prière Lunaire",
@ -3529,7 +3529,7 @@
},
"gMaxRapidFlow": {
"name": "Multicoup G-Max",
"effect": "Une attaque de type Eau que seul un Shifours Gigamax peut utiliser. Cet enchainement de coups permet dignorer la capacité Gardomax."
"effect": "Une attaque de type Eau que seul un Shifours Gigamax peut utiliser. Cet enchaînement de coups permet dignorer la capacité Gardomax."
},
"teraBlast": {
"name": "Téra Explosion",
@ -3712,8 +3712,8 @@
"effect": "Le lanceur projette de leau pressurisée qui entaille la cible comme une lame. Taux de critiques élevé."
},
"blazingTorque": {
"name": "Crash Brulant",
"effect": "Crash Brulant inflige des dégâts et possède 30 % de chances de bruler ladversaire."
"name": "Crash Brûlant",
"effect": "Crash Brûlant inflige des dégâts et possède 30 % de chances de brûler ladversaire."
},
"wickedTorque": {
"name": "Crash Obscur",
@ -3737,7 +3737,7 @@
},
"matchaGotcha": {
"name": "Mortier Matcha",
"effect": "Le lanceur remue son thé et en bombarde la cible. La moitié des dégâts infligés sont convertis en PV pour le lanceur. Cette capacité peut aussi bruler la cible."
"effect": "Le lanceur remue son thé et en bombarde la cible. La moitié des dégâts infligés sont convertis en PV pour le lanceur. Cette capacité peut aussi brûler la cible."
},
"syrupBomb": {
"name": "Bombe au Sirop",
@ -3760,8 +3760,8 @@
"effect": "Le lanceur attaque en tirant un rayon lumineux. Il arrive parfois que toutes les têtes agissent ensemble, ce qui double la puissance de la capacité."
},
"burningBulwark": {
"name": "Rempart Brulant",
"effect": "Le lanceur se protège contre les attaques grâce à son pelage incandescent, et si un assaillant utilise une attaque directe contre lui, il le brule."
"name": "Rempart Brûlant",
"effect": "Le lanceur se protège contre les attaques grâce à son pelage incandescent, et si un assaillant utilise une attaque directe contre lui, il le brûle."
},
"thunderclap": {
"name": "Vif Éclair",
@ -3784,7 +3784,7 @@
"effect": "Le lanceur galvanise ses alliés avec un encouragement draconique qui augmente leur taux de critiques. Leffet est plus puissant si les alliés ont le type Dragon."
},
"alluringVoice": {
"name": "Voix Envoutante",
"name": "Voix Envoûtante",
"effect": "Le lanceur attaque la cible avec sa voix angélique. Cette capacité rend la cible confuse si ses stats ont augmenté pendant ce tour."
},
"temperFlare": {
@ -3804,7 +3804,7 @@
"effect": "Le lanceur réagit instinctivement au moindre mouvement et donne un coup de paume qui apeure la cible. Échoue si cette dernière na pas utilisé une attaque prioritaire."
},
"malignantChain": {
"name": "Chaine Malsaine",
"effect": "Le lanceur ligote la cible avec une chaine faite de poison et lui injecte un venin corrosif, ce qui peut aussi gravement lempoisonner."
"name": "Chaîne Malsaine",
"effect": "Le lanceur ligote la cible avec une chaîne faite de poison et lui injecte un venin corrosif, ce qui peut aussi gravement lempoisonner."
}
}
}

View File

@ -11,7 +11,7 @@
"baker": "Boulangère",
"battle_girl": "Combattante",
"beauty": "Canon",
"beginners": "Débutants",
"beginners": "Beginners",
"biker": "Motard",
"black_belt": "Karatéka",
"breeder": "Éleveur",
@ -29,7 +29,7 @@
"depot_agent": "Cheminot",
"doctor": "Docteur",
"doctor_female": "Docteure",
"firebreather": "Crache-Feu",
"firebreather": "Firebreather",
"fisherman": "Pêcheur",
"fisherman_female": "Pêcheuse",
"gentleman": "Gentleman",
@ -68,7 +68,7 @@
"pokémon_rangers": "Pokémon Rangers",
"ranger": "Ranger",
"restaurant_staff": "Serveurs",
"rich": "Gentleman",
"rich": "Rich",
"rich_female": "Mondaine",
"rich_boy": "Gentleman",
"rich_couple": "Couple de Bourgeois",
@ -118,4 +118,4 @@
"flare_grunt": "Sbire de la Team Flare",
"flare_grunt_female": "Sbire de la Team Flare",
"flare_grunts": "Sbires de la Team Flare"
}
}

View File

@ -2913,7 +2913,7 @@
},
"zippyZap": {
"name": "Sprintaboom",
"effect": "Un attacco elettrico ad altissima velocità. Questa mossa ha priorità alta e infligge sicuramente un brutto colpo."
"effect": "Un attacco elettrico ad altissima velocità. Questa mossa ha priorità alta e aumenta l'elusione dell'utilizzatore."
},
"splishySplash": {
"name": "Surfasplash",
@ -3807,4 +3807,4 @@
"name": "Intossicatena",
"effect": "Il Pokémon logora il bersaglio avvolgendolo con le sue catene fatte di veleno e iniettandogli delle tossine che possono anche iperavvelenarlo."
}
}
}

View File

@ -1,42 +1 @@
{
"SEND_OUT": "Manda in campo",
"SUMMARY": "Sommario",
"CANCEL": "Annulla",
"RELEASE": "Rilascia",
"APPLY": "Applica",
"TEACH": "Insegna",
"SPLICE": "Unisci",
"UNSPLICE": "Dividi",
"ACTIVATE": "Attiva",
"DEACTIVATE": "Disattiva",
"TRANSFER": "Trasferisci",
"ALL": "Tutto",
"PASS_BATON": "Staffetta",
"UNPAUSE_EVOLUTION": "Consenti evoluzione",
"REVIVE": "Revitalizza",
"RENAME": "Rinomina",
"choosePokemon": "Scegli un Pokémon.",
"doWhatWithThisPokemon": "Hai selezionato questo Pokémon.",
"noEnergy": "{{pokemonName}} non ha più energie\nper lottare!",
"hasEnergy": "{{pokemonName}} ha ancora energie\nper lottare!",
"cantBeUsed": "{{pokemonName}} non può essere usato\nin questa sfida!",
"tooManyItems": "{{pokemonName}} possiede già\nquest'oggetto in abbondanza!",
"anyEffect": "Non avrebbe alcun effetto.",
"unpausedEvolutions": "{{pokemonName}} può di nuovo evolversi.",
"unspliceConfirmation": "Vuoi davvero dividere {{fusionName}}\nda {{pokemonName}}? {{fusionName}} andrà perduto.",
"wasReverted": "{{fusionName}} è tornato ad essere {{pokemonName}}.",
"releaseConfirmation": "Vuoi davvero liberare {{pokemonName}}?",
"releaseInBattle": "Non puoi liberare un Pokémon che sta combattendo!",
"selectAMove": "Scegli una mossa.",
"changeQuantity": "Scegli un oggetto da trasferire.\nUsa < e > per cambiarne la quantità.",
"selectAnotherPokemonToSplice": "Scegli un altro Pokémon da unire.",
"cancel": "Annulla",
"goodbye": "Addio, {{pokemonName}}!",
"byebye": "Ciao ciao, {{pokemonName}}!",
"farewell": "Arrivederci, {{pokemonName}}!",
"soLong": "È stato bello, {{pokemonName}}!",
"thisIsWhereWePart": "Le nostre strade si dividono, {{pokemonName}}!",
"illMissYou": "Mi mancherai, {{pokemonName}}!",
"illNeverForgetYou": "Non ti dimenticherò, {{pokemonName}}!",
"untilWeMeetAgain": "Alla prossima, {{pokemonName}}!"
}
{}

View File

@ -10,5 +10,5 @@
"eternamaxChange": "{{preName}} si Dynamaxxa infinitamente\nin {{pokemonName}}!",
"revertChange": "{{pokemonName}} è tornato\nalla sua forma originaria!",
"formChange": "{{preName}} ha cambiato forma!",
"disguiseChange": "Il costume ha assorbito lattacco!"
"disguiseChange": "Its disguise served it as a decoy!"
}

View File

@ -1,6 +1,6 @@
{
"confirmStartTeam": "Vuoi iniziare con questi Pokémon?",
"confirmExit": "Vuoi tornare alla schermata principale?",
"confirmExit": "Do you want to exit?",
"invalidParty": "Questo squadra iniziale non è valida!",
"gen1": "1ª",
"gen2": "2ª",
@ -21,13 +21,13 @@
"toggleIVs": "Vedi/Nascondi IV",
"manageMoves": "Gestisci mosse",
"manageNature": "Gestisci natura",
"addToFavorites": "Aggiungi ai preferiti",
"removeFromFavorites": "Rimuovi dai preferiti",
"addToFavorites": "Add to Favorites",
"removeFromFavorites": "Remove from Favorites",
"useCandies": "Usa caramelle",
"selectNature": "Seleziona natura.",
"selectMoveSwapOut": "Seleziona una mossa da scambiare.",
"selectMoveSwapWith": "Seleziona una mossa da scambiare con",
"sameSpeciesEgg": "Compra un uovo",
"sameSpeciesEgg": "Buy an Egg",
"unlockPassive": "Sblocca passiva",
"reduceCost": "Riduci costo",
"cycleShiny": ": Shiny",
@ -36,7 +36,7 @@
"cycleAbility": ": Abilità",
"cycleNature": ": Natura",
"cycleVariant": ": Variante",
"goFilter": ": Vai ai filtri",
"goFilter": ": Go to filters",
"enablePassive": "Attiva passiva",
"disablePassive": "Disattiva passiva",
"locked": "Bloccato",

View File

@ -1,16 +1 @@
{
"misty": "Nebbioso",
"mistyStartMessage": "Ai piedi dei Pokémon si addensa la nebbia.",
"mistyClearMessage": "La nebbia si dissolve.",
"mistyBlockMessage": "Il Campo Nebbioso protegge {{pokemonNameWithAffix}}!",
"electric": "Elettrico",
"electricStartMessage": "Ai piedi dei Pokémon si accumula dellelettricità.",
"electricClearMessage": "Lelettricità svanisce.",
"grassy": "Erboso",
"grassyStartMessage": "Ai piedi dei Pokémon cresce rigogliosa lerba.",
"grassyClearMessage": "Lerba sparisce.",
"psychic": "Psichico",
"psychicStartMessage": "Nel campo si avverte una strana sensazione...",
"psychicClearMessage": "La strana sensazione nel campo è svanita!",
"defaultBlockMessage": "Il Campo {{terrainName}} protegge {{pokemonNameWithAffix}}!"
}
{}

View File

@ -124,25 +124,25 @@
"rival": "Finn",
"rival_female": "Ivy",
"archer": "Archer",
"ariana": "Atena",
"proton": "Milas",
"petrel": "Maxus",
"tabitha": "Ottavio",
"courtney": "Rossella",
"shelly": "Ada",
"matt": "Alan",
"mars": "Martes",
"jupiter": "Giovia",
"saturn": "Saturno",
"zinzolin": "Violante",
"rood": "Ross",
"xerosic": "Xante",
"bryony": "Bromelia",
"maxie": "Max",
"archie": "Ivan",
"ariana": "Ariana",
"proton": "Proton",
"petrel": "Petrel",
"tabitha": "Tabitha",
"courtney": "Courtney",
"shelly": "Shelly",
"matt": "Matt",
"mars": "Mars",
"jupiter": "Jupiter",
"saturn": "Saturn",
"zinzolin": "Zinzolin",
"rood": "Rood",
"xerosic": "Xerosic",
"bryony": "Bryony",
"maxie": "Maxie",
"archie": "Archie",
"cyrus": "Cyrus",
"ghetsis": "Ghecis",
"lysandre": "Elisio",
"ghetsis": "Ghetsis",
"lysandre": "Lysandre",
"blue_red_double": "Blu & Rosso",
"red_blue_double": "Rosso & Blu",
"tate_liza_double": "Tell & Pat",

View File

@ -10,22 +10,22 @@
"rival": "Rivale",
"professor": "Professore",
"frontier_brain": "Asso lotta",
"rocket_boss": "Capo Rocket",
"magma_boss": "Capo Magma",
"aqua_boss": "Capo Idro",
"galactic_boss": "Capo Galassia",
"plasma_boss": "Capo Plasma",
"flare_boss": "Capo Flare",
"rocket_admin": "Tenente Team Rocket",
"rocket_admin_female": "Tenente Team Rocket",
"magma_admin": "Magmatenente",
"magma_admin_female": "Magmatenente",
"aqua_admin": "Idrotenente",
"aqua_admin_female": "Idrotenente",
"galactic_commander": "Comandante Galassia",
"galactic_commander_female": "Comandante Galassia",
"plasma_sage": "Saggio Team Plasma",
"plasma_admin": "Tenente Team Plasma",
"flare_admin": "Ufficiale Team Flare",
"flare_admin_female": "Ufficiale Team Flare"
"rocket_boss": "Team Rocket Boss",
"magma_boss": "Team Magma Boss",
"aqua_boss": "Team Aqua Boss",
"galactic_boss": "Team Galactic Boss",
"plasma_boss": "Team Plasma Boss",
"flare_boss": "Team Flare Boss",
"rocket_admin": "Team Rocket Admin",
"rocket_admin_female": "Team Rocket Admin",
"magma_admin": "Team Magma Admin",
"magma_admin_female": "Team Magma Admin",
"aqua_admin": "Team Aqua Admin",
"aqua_admin_female": "Team Aqua Admin",
"galactic_commander": "Team Galactic Commander",
"galactic_commander_female": "Team Galactic Commander",
"plasma_sage": "Team Plasma Sage",
"plasma_admin": "Team Plasma Admin",
"flare_admin": "Team Flare Admin",
"flare_admin_female": "Team Flare Admin"
}

View File

@ -2913,7 +2913,7 @@
},
"zippyZap": {
"name": "파찌파찌액셀",
"effect": "맹렬한 속도의 전격 공격. 반드시 선제공격할 수 있고 급소에 맞는다."
"effect": "맹렬한 속도의 전격 공격. 반드시 선제공격할 수 있고 자신의 회피율을 높인다."
},
"splishySplash": {
"name": "참방참방서핑",
@ -3807,4 +3807,4 @@
"name": "악독사슬",
"effect": "독으로 된 사슬로 상대를 휘감은 뒤 독소를 흘려보내어 해치운다. 맹독 상태로 만들 때가 있다."
}
}
}

View File

@ -2913,7 +2913,7 @@
},
"zippyZap": {
"name": "Zippy Zap",
"effect": "O usuário ataca o alvo com rajadas de eletricidade em alta velocidade. Esse movimento sempre vai primeiro e resulta em um golpe crítico."
"effect": "O usuário ataca o alvo com rajadas de eletricidade em alta velocidade. Esse movimento sempre vai primeiro e aumenta a Evasão do usuário."
},
"splishySplash": {
"name": "Splishy Splash",
@ -3807,4 +3807,4 @@
"name": "Malignant Chain",
"effect": "O usuário derrama toxinas no alvo envolvendo-o em uma corrente tóxica e corrosiva. Isso também pode deixar o alvo seriamente envenenado."
}
}
}

View File

@ -2913,7 +2913,7 @@
},
"zippyZap": {
"name": "电电加速",
"effect": "迅猛无比的电击。必定能够先制攻击,击中对方的要害。"
"effect": "迅猛无比的电击。必定能够先制攻击,\n并且提高自己的闪避率。"
},
"splishySplash": {
"name": "滔滔冲浪",
@ -3807,4 +3807,4 @@
"name": "邪毒锁链",
"effect": "用由毒形成的锁链缠住对手注入毒\n素加以侵蚀。有时会让对手陷入剧毒状态"
}
}
}

View File

@ -311,6 +311,8 @@ export class MoveEffectPhase extends PokemonPhase {
}
end() {
const move = this.move.getMove();
move.type = move.defaultType;
const user = this.getUserPokemon();
/**
* If this phase isn't for the invoked move's last strike,

View File

@ -1,18 +1,19 @@
import { BattlerIndex } from "#app/battle";
import { allAbilities } from "#app/data/ability";
import { Abilities } from "#app/enums/abilities";
import { Abilities } from "#app/enums/abilities.js";
import GameManager from "#test/utils/gameManager";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import { WeatherType } from "#app/enums/weather-type";
import { BattlerIndex } from "#app/battle";
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
import { DamagePhase } from "#app/phases/damage-phase";
import { MovePhase } from "#app/phases/move-phase";
import { PostSummonPhase } from "#app/phases/post-summon-phase";
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
import { TurnEndPhase } from "#app/phases/turn-end-phase";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { VictoryPhase } from "#app/phases/victory-phase";
import { allAbilities } from "#app/data/ability";
describe("Abilities - Forecast", () => {
let phaserGame: Phaser.Game;
@ -30,7 +31,7 @@ describe("Abilities - Forecast", () => {
* @param initialForm The initial form pre form change
*/
const testWeatherFormChange = async (game: GameManager, weather: WeatherType, form: number, initialForm?: number) => {
game.override.weather(weather).starterForms({ [Species.CASTFORM]: initialForm });
game.override.weather(weather).starterForms({[Species.CASTFORM]: initialForm});
await game.startBattle([Species.CASTFORM]);
game.move.select(Moves.SPLASH);
@ -52,6 +53,54 @@ describe("Abilities - Forecast", () => {
expect(game.scene.getPlayerPokemon()?.formIndex).toBe(NORMAL_FORM);
};
/**
* Tests transforming back to match the weather when Cloud Nine/Air Lock user is fainted
* @param {GameManager} game The game manager instance
* @param {Abilities} ability The ability that will go out of battle (faint)
*/
const testTransformAfterAbilityFaint = async (game: GameManager, ability: Abilities) => {
game.override.enemyAbility(ability).weather(WeatherType.SNOW).enemySpecies(Species.SHUCKLE);
await game.startBattle([Species.CASTFORM]);
const castform = game.scene.getPlayerPokemon();
expect(castform?.formIndex).toBe(NORMAL_FORM);
game.move.select(Moves.TACKLE);
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
await game.phaseInterceptor.to(DamagePhase);
await game.doKillOpponents();
await game.phaseInterceptor.to(VictoryPhase);
expect(castform?.formIndex).toBe(SNOWY_FORM);
};
/**
* Tests transforming back to match the weather when Cloud Nine/Air Lock user is switched out
* @param {GameManager} game The game manager instance
* @param {Abilities} ability The ability that will go out of battle (switched out)
*/
const testTransformAfterAbilitySwitchOut = async (game: GameManager, ability: Abilities) => {
game.override
.weather(WeatherType.SNOW)
.enemySpecies(Species.CASTFORM)
.enemyAbility(Abilities.FORECAST)
.ability(ability);
await game.startBattle([Species.PICHU, Species.PIKACHU]);
const castform = game.scene.getEnemyPokemon();
// We mock the return value of the second Pokemon to be other than Air Lock/Cloud Nine
vi.spyOn(game.scene.getParty()[1]!, "getAbility").mockReturnValue(allAbilities[Abilities.BALL_FETCH]);
expect(game.scene.getParty()[1]?.hasAbility(Abilities.BALL_FETCH));
expect(castform?.formIndex).toBe(NORMAL_FORM);
game.doSwitchPokemon(1);
await game.phaseInterceptor.to(MovePhase);
expect(castform?.formIndex).toBe(SNOWY_FORM);
};
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
@ -64,127 +113,55 @@ describe("Abilities - Forecast", () => {
beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.moveset([Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.TACKLE])
.enemySpecies(Species.MAGIKARP)
game.override.moveset([ Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.TACKLE ])
.enemyMoveset(SPLASH_ONLY)
.enemyAbility(Abilities.BALL_FETCH);
});
it("changes form based on weather", async () => {
game.override
.moveset([Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.SNOWSCAPE, Moves.SPLASH])
.battleType("double")
.starterForms({
[Species.KYOGRE]: 1,
[Species.GROUDON]: 1,
[Species.RAYQUAZA]: 1
});
await game.startBattle([Species.CASTFORM, Species.FEEBAS, Species.KYOGRE, Species.GROUDON, Species.RAYQUAZA, Species.ALTARIA]);
it("changes to Sunny Form during Harsh Sunlight", async () => {
await testWeatherFormChange(game, WeatherType.SUNNY, SUNNY_FORM);
});
vi.spyOn(game.scene.getParty()[5], "getAbility").mockReturnValue(allAbilities[Abilities.CLOUD_NINE]);
it("changes to Sunny Form during Extreme Harsh Sunlight", async () => {
await testWeatherFormChange(game, WeatherType.HARSH_SUN, SUNNY_FORM);
});
const castform = game.scene.getPlayerField()[0];
expect(castform.formIndex).toBe(NORMAL_FORM);
it("changes to Rainy Form during Rain", async () => {
await testWeatherFormChange(game, WeatherType.RAIN, RAINY_FORM);
});
game.move.select(Moves.RAIN_DANCE);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
it("changes to Rainy Form during Heavy Rain", async () => {
await testWeatherFormChange(game, WeatherType.HEAVY_RAIN, RAINY_FORM);
});
expect(castform.formIndex).toBe(RAINY_FORM);
it("changes to Snowy Form during Hail", async () => {
await testWeatherFormChange(game, WeatherType.HAIL, SNOWY_FORM);
});
game.move.select(Moves.SUNNY_DAY);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
it("changes to Snowy Form during Snow", async () => {
await testWeatherFormChange(game, WeatherType.SNOW, SNOWY_FORM);
});
expect(castform.formIndex).toBe(SUNNY_FORM);
it("reverts to Normal Form during Sandstorm", async () => {
await testWeatherFormChange(game, WeatherType.SANDSTORM, NORMAL_FORM, SUNNY_FORM);
});
game.move.select(Moves.SNOWSCAPE);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
it("reverts to Normal Form during Fog", async () => {
await testWeatherFormChange(game, WeatherType.FOG, NORMAL_FORM, SUNNY_FORM);
});
expect(castform.formIndex).toBe(SNOWY_FORM);
game.override.moveset([Moves.HAIL, Moves.SANDSTORM, Moves.SNOWSCAPE, Moves.SPLASH]);
game.move.select(Moves.SANDSTORM);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(NORMAL_FORM);
game.move.select(Moves.HAIL);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(SNOWY_FORM);
game.move.select(Moves.SPLASH);
game.doSwitchPokemon(2); // Feebas now 2, Kyogre 1
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(RAINY_FORM);
game.move.select(Moves.SPLASH);
game.doSwitchPokemon(3); // Kyogre now 3, Groudon 1
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(SUNNY_FORM);
game.move.select(Moves.SPLASH);
game.doSwitchPokemon(4); // Groudon now 4, Rayquaza 1
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(NORMAL_FORM);
game.move.select(Moves.SPLASH);
game.doSwitchPokemon(2); // Rayquaza now 2, Feebas 1
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(NORMAL_FORM);
game.move.select(Moves.SNOWSCAPE);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(SNOWY_FORM);
game.move.select(Moves.SPLASH);
game.doSwitchPokemon(5); // Feebas now 5, Altaria 1
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(NORMAL_FORM);
game.move.select(Moves.SPLASH);
game.doSwitchPokemon(5); // Altaria now 5, Feebas 1
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
expect(castform.formIndex).toBe(SNOWY_FORM);
game.scene.arena.trySetWeather(WeatherType.FOG, false);
game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("TurnStartPhase");
expect(castform.formIndex).toBe(NORMAL_FORM);
}, 30 * 1000);
it("reverts to Normal Form during Strong Winds", async () => {
await testWeatherFormChange(game, WeatherType.STRONG_WINDS, NORMAL_FORM, SUNNY_FORM);
});
it("reverts to Normal Form during Clear weather", async () => {
await testWeatherFormChange(game, WeatherType.NONE, NORMAL_FORM, SUNNY_FORM);
});
it("reverts to Normal Form if a Pokémon on the field has Cloud Nine", async () => {
await testRevertFormAgainstAbility(game, Abilities.CLOUD_NINE);
});
it("reverts to Normal Form if a Pokémon on the field has Air Lock", async () => {
await testRevertFormAgainstAbility(game, Abilities.AIR_LOCK);
});
@ -200,50 +177,47 @@ describe("Abilities - Forecast", () => {
expect(game.scene.getEnemyPokemon()?.formIndex).not.toBe(RAINY_FORM);
});
it("reverts to Normal Form when Castform loses Forecast, changes form to match the weather when it regains it", async () => {
game.override.moveset([Moves.SKILL_SWAP, Moves.WORRY_SEED, Moves.SPLASH]).weather(WeatherType.RAIN).battleType("double");
await game.startBattle([Species.CASTFORM, Species.FEEBAS]);
const castform = game.scene.getPlayerField()[0];
expect(castform.formIndex).toBe(RAINY_FORM);
game.move.select(Moves.SKILL_SWAP, 0, BattlerIndex.PLAYER_2);
game.move.select(Moves.SKILL_SWAP, 1, BattlerIndex.PLAYER);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to("MoveEndPhase");
expect(castform.formIndex).toBe(NORMAL_FORM);
await game.phaseInterceptor.to("MoveEndPhase");
expect(castform.formIndex).toBe(RAINY_FORM);
await game.toNextTurn();
it("cannot be copied", async () => {
game.override.enemyAbility(Abilities.TRACE);
await game.startBattle([Species.CASTFORM]);
game.move.select(Moves.SPLASH);
game.move.select(Moves.WORRY_SEED, 1, BattlerIndex.PLAYER);
await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to("MoveEndPhase");
expect(castform.formIndex).toBe(NORMAL_FORM);
expect(game.scene.getEnemyPokemon()?.hasAbility(Abilities.FORECAST)).toBe(false);
});
it("reverts to Normal Form when Forecast is suppressed, changes form to match the weather when it regains it", async () => {
game.override.enemyMoveset(Array(4).fill(Moves.GASTRO_ACID)).weather(WeatherType.RAIN);
await game.startBattle([Species.CASTFORM, Species.PIKACHU]);
const castform = game.scene.getPlayerPokemon()!;
it("(Skill Swap) reverts to Normal Form when Castform loses Forecast, changes form to match the weather when it regains it", async () => {
game.override.moveset([Moves.SKILL_SWAP]).weather(WeatherType.RAIN);
await game.startBattle([Species.CASTFORM]);
const castform = game.scene.getPlayerPokemon();
expect(castform.formIndex).toBe(RAINY_FORM);
// First turn - Forecast is suppressed
game.move.select(Moves.SPLASH);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.move.forceHit();
expect(castform?.formIndex).toBe(RAINY_FORM);
// First turn - loses Forecast
game.move.select(Moves.SKILL_SWAP);
await game.phaseInterceptor.to(TurnEndPhase);
expect(castform.summonData.abilitySuppressed).toBe(true);
expect(castform.formIndex).toBe(NORMAL_FORM);
expect(castform?.formIndex).toBe(NORMAL_FORM);
// Second turn - regains Forecast
game.move.select(Moves.SKILL_SWAP);
await game.phaseInterceptor.to(TurnEndPhase);
expect(castform?.formIndex).toBe(RAINY_FORM);
});
it("(Worry Seed) reverts to Normal Form when Castform loses Forecast, changes form to match the weather when it regains it", async () => {
game.override.enemyMoveset(Array(4).fill(Moves.WORRY_SEED)).weather(WeatherType.RAIN);
await game.startBattle([Species.CASTFORM, Species.PIKACHU]);
const castform = game.scene.getPlayerPokemon();
expect(castform?.formIndex).toBe(RAINY_FORM);
// First turn - loses Forecast
game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to(TurnEndPhase);
expect(castform?.formIndex).toBe(NORMAL_FORM);
await game.toNextTurn();
@ -255,8 +229,67 @@ describe("Abilities - Forecast", () => {
game.doSwitchPokemon(1);
await game.phaseInterceptor.to(MovePhase);
expect(castform.summonData.abilitySuppressed).toBe(false);
expect(castform.formIndex).toBe(RAINY_FORM);
expect(castform?.formIndex).toBe(RAINY_FORM);
});
it("reverts to Normal Form when active weather ends", async () => {
await game.startBattle([Species.CASTFORM]);
const castform = game.scene.getPlayerPokemon();
game.move.select(Moves.SUNNY_DAY);
await game.phaseInterceptor.to(TurnEndPhase);
while (game.scene.arena.weather && game.scene.arena.weather.turnsLeft > 0) {
game.move.select(Moves.SPLASH);
expect(castform?.formIndex).toBe(SUNNY_FORM);
await game.toNextTurn();
}
expect(castform?.formIndex).toBe(NORMAL_FORM);
});
it("reverts to Normal Form when Forecast is suppressed, changes form to match the weather when it regains it", async () => {
game.override.enemyMoveset(Array(4).fill(Moves.GASTRO_ACID)).weather(WeatherType.RAIN);
await game.startBattle([Species.CASTFORM, Species.PIKACHU]);
const castform = game.scene.getPlayerPokemon();
expect(castform?.formIndex).toBe(RAINY_FORM);
// First turn - Forecast is suppressed
game.move.select(Moves.SPLASH);
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]);
await game.move.forceHit();
await game.phaseInterceptor.to(TurnEndPhase);
expect(castform?.summonData.abilitySuppressed).toBe(true);
expect(castform?.formIndex).toBe(NORMAL_FORM);
await game.toNextTurn();
// Second turn - switch out Castform, regains Forecast
game.doSwitchPokemon(1);
await game.toNextTurn();
// Third turn - switch in Castform
game.doSwitchPokemon(1);
await game.phaseInterceptor.to(MovePhase);
expect(castform?.summonData.abilitySuppressed).toBe(false);
expect(castform?.formIndex).toBe(RAINY_FORM);
});
it("if a Pokémon transforms into Castform, the Pokémon will remain in the same form as the target Castform, regardless of the weather", async () => {
game.override.enemyMoveset(Array(4).fill(Moves.TRANSFORM));
await game.startBattle([Species.CASTFORM]);
game.move.select(Moves.SUNNY_DAY);
await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]);
await game.phaseInterceptor.to(TurnEndPhase);
expect(game.scene.getPlayerPokemon()?.formIndex).toBe(SUNNY_FORM);
expect(game.scene.getEnemyPokemon()?.formIndex).toBe(NORMAL_FORM);
});
it("does not change Castform's form until after Stealth Rock deals damage", async () => {
@ -271,15 +304,31 @@ describe("Abilities - Forecast", () => {
game.doSwitchPokemon(1);
await game.phaseInterceptor.to(PostSummonPhase);
const castform = game.scene.getPlayerPokemon()!;
const castform = game.scene.getPlayerPokemon();
// Damage phase should come first
await game.phaseInterceptor.to(DamagePhase);
expect(castform.hp).toBeLessThan(castform.getMaxHp());
expect(castform?.hp).toBeLessThan(castform?.getMaxHp() ?? 0);
// Then change form
await game.phaseInterceptor.to(QuietFormChangePhase);
expect(castform.formIndex).toBe(RAINY_FORM);
expect(castform?.formIndex).toBe(RAINY_FORM);
});
it("transforms to weather-based form when Pokemon with Air Lock is fainted", async () => {
await testTransformAfterAbilityFaint(game, Abilities.AIR_LOCK);
});
it("transforms to weather-based form when Pokemon with Cloud Nine is fainted", async () => {
await testTransformAfterAbilityFaint(game, Abilities.CLOUD_NINE);
});
it("transforms to weather-based form when Pokemon with Air Lock is switched out", async () => {
await testTransformAfterAbilitySwitchOut(game, Abilities.AIR_LOCK);
});
it("transforms to weather-based form when Pokemon with Cloud Nine is switched out", async () => {
await testTransformAfterAbilitySwitchOut(game, Abilities.CLOUD_NINE);
});
it("should be in Normal Form after the user is switched out", async () => {

View File

@ -1,133 +0,0 @@
import { BattlerIndex } from "#app/battle";
import { allMoves } from "#app/data/move";
import { Type } from "#app/data/type";
import { Abilities } from "#app/enums/abilities";
import { Moves } from "#app/enums/moves";
import { Species } from "#app/enums/species";
import { HitResult } from "#app/field/pokemon";
import GameManager from "#test/utils/gameManager";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const TIMEOUT = 20 * 1000;
describe("Abilities - Galvanize", () => {
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")
.startingLevel(100)
.ability(Abilities.GALVANIZE)
.moveset([Moves.TACKLE, Moves.REVELATION_DANCE, Moves.FURY_SWIPES])
.enemySpecies(Species.DUSCLOPS)
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(SPLASH_ONLY)
.enemyLevel(100);
});
it("should change Normal-type attacks to Electric type and boost their power", async () => {
await game.startBattle();
const playerPokemon = game.scene.getPlayerPokemon()!;
vi.spyOn(playerPokemon, "getMoveType");
const enemyPokemon = game.scene.getEnemyPokemon()!;
vi.spyOn(enemyPokemon, "apply");
const move = allMoves[Moves.TACKLE];
vi.spyOn(move, "calculateBattlePower");
game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("BerryPhase", false);
expect(playerPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC);
expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.EFFECTIVE);
expect(move.calculateBattlePower).toHaveReturnedWith(48);
expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp());
}, TIMEOUT);
it("should cause Normal-type attacks to activate Volt Absorb", async () => {
game.override.enemyAbility(Abilities.VOLT_ABSORB);
await game.startBattle();
const playerPokemon = game.scene.getPlayerPokemon()!;
vi.spyOn(playerPokemon, "getMoveType");
const enemyPokemon = game.scene.getEnemyPokemon()!;
vi.spyOn(enemyPokemon, "apply");
enemyPokemon.hp = Math.floor(enemyPokemon.getMaxHp() * 0.8);
game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("BerryPhase", false);
expect(playerPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC);
expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.NO_EFFECT);
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp());
}, TIMEOUT);
it("should not change the type of variable-type moves", async () => {
game.override.enemySpecies(Species.MIGHTYENA);
await game.startBattle([Species.ESPEON]);
const playerPokemon = game.scene.getPlayerPokemon()!;
vi.spyOn(playerPokemon, "getMoveType");
const enemyPokemon = game.scene.getEnemyPokemon()!;
vi.spyOn(enemyPokemon, "apply");
game.move.select(Moves.REVELATION_DANCE);
await game.phaseInterceptor.to("BerryPhase", false);
expect(playerPokemon.getMoveType).not.toHaveLastReturnedWith(Type.ELECTRIC);
expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.NO_EFFECT);
expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp());
}, TIMEOUT);
it("should affect all hits of a Normal-type multi-hit move", async () => {
await game.startBattle();
const playerPokemon = game.scene.getPlayerPokemon()!;
vi.spyOn(playerPokemon, "getMoveType");
const enemyPokemon = game.scene.getEnemyPokemon()!;
vi.spyOn(enemyPokemon, "apply");
game.move.select(Moves.FURY_SWIPES);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.move.forceHit();
await game.phaseInterceptor.to("MoveEffectPhase");
expect(playerPokemon.turnData.hitCount).toBeGreaterThan(1);
expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp());
while (playerPokemon.turnData.hitsLeft > 0) {
const enemyStartingHp = enemyPokemon.hp;
await game.phaseInterceptor.to("MoveEffectPhase");
expect(playerPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC);
expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp);
}
expect(enemyPokemon.apply).not.toHaveReturnedWith(HitResult.NO_EFFECT);
}, TIMEOUT);
});

View File

@ -76,7 +76,7 @@ describe("Abilities - Libero", () => {
expect(leadPokemon.summonData.abilitiesApplied.filter((a) => a === Abilities.LIBERO)).toHaveLength(1);
const leadPokemonType = Type[leadPokemon.getTypes()[0]];
const moveType = Type[allMoves[Moves.AGILITY].type];
const moveType = Type[allMoves[Moves.AGILITY].defaultType];
expect(leadPokemonType).not.toBe(moveType);
await game.toNextTurn();
@ -249,7 +249,7 @@ describe("Abilities - Libero", () => {
const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined);
leadPokemon.summonData.types = [allMoves[Moves.SPLASH].type];
leadPokemon.summonData.types = [allMoves[Moves.SPLASH].defaultType];
game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to(TurnEndPhase);
@ -357,6 +357,6 @@ function testPokemonTypeMatchesDefaultMoveType(pokemon: PlayerPokemon, move: Mov
expect(pokemon.summonData.abilitiesApplied).toContain(Abilities.LIBERO);
expect(pokemon.getTypes()).toHaveLength(1);
const pokemonType = Type[pokemon.getTypes()[0]],
moveType = Type[allMoves[move].type];
moveType = Type[allMoves[move].defaultType];
expect(pokemonType).toBe(moveType);
}

View File

@ -76,7 +76,7 @@ describe("Abilities - Protean", () => {
expect(leadPokemon.summonData.abilitiesApplied.filter((a) => a === Abilities.PROTEAN)).toHaveLength(1);
const leadPokemonType = Type[leadPokemon.getTypes()[0]];
const moveType = Type[allMoves[Moves.AGILITY].type];
const moveType = Type[allMoves[Moves.AGILITY].defaultType];
expect(leadPokemonType).not.toBe(moveType);
await game.toNextTurn();
@ -249,7 +249,7 @@ describe("Abilities - Protean", () => {
const leadPokemon = game.scene.getPlayerPokemon()!;
expect(leadPokemon).not.toBe(undefined);
leadPokemon.summonData.types = [allMoves[Moves.SPLASH].type];
leadPokemon.summonData.types = [allMoves[Moves.SPLASH].defaultType];
game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to(TurnEndPhase);
@ -357,6 +357,6 @@ function testPokemonTypeMatchesDefaultMoveType(pokemon: PlayerPokemon, move: Mov
expect(pokemon.summonData.abilitiesApplied).toContain(Abilities.PROTEAN);
expect(pokemon.getTypes()).toHaveLength(1);
const pokemonType = Type[pokemon.getTypes()[0]],
moveType = Type[allMoves[move].type];
moveType = Type[allMoves[move].defaultType];
expect(pokemonType).toBe(moveType);
}

View File

@ -1,70 +0,0 @@
import { allMoves } from "#app/data/move";
import { getPokemonSpecies } from "#app/data/pokemon-species";
import { TrainerSlot } from "#app/data/trainer-config";
import { Abilities } from "#app/enums/abilities";
import { Moves } from "#app/enums/moves";
import { Species } from "#app/enums/species";
import * as Messages from "#app/messages";
import GameManager from "#test/utils/gameManager";
import Phaser from "phaser";
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
function testMoveEffectiveness(game: GameManager, move: Moves, targetSpecies: Species,
expected: number, targetAbility: Abilities = Abilities.BALL_FETCH): void {
// Suppress getPokemonNameWithAffix because it calls on a null battle spec
vi.spyOn(Messages, "getPokemonNameWithAffix").mockReturnValue("");
game.override.enemyAbility(targetAbility);
const user = game.scene.addPlayerPokemon(getPokemonSpecies(Species.SNORLAX), 5);
const target = game.scene.addEnemyPokemon(getPokemonSpecies(targetSpecies), 5, TrainerSlot.NONE);
expect(target.getMoveEffectiveness(user, allMoves[move])).toBe(expected);
}
describe("Moves - Type Effectiveness", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
game = new GameManager(phaserGame);
game.override.ability(Abilities.BALL_FETCH);
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
it("Normal-type attacks are neutrally effective against Normal-type Pokemon",
() => testMoveEffectiveness(game, Moves.TACKLE, Species.SNORLAX, 1)
);
it("Normal-type attacks are not very effective against Steel-type Pokemon",
() => testMoveEffectiveness(game, Moves.TACKLE, Species.REGISTEEL, 0.5)
);
it("Normal-type attacks are doubly resisted by Steel/Rock-type Pokemon",
() => testMoveEffectiveness(game, Moves.TACKLE, Species.AGGRON, 0.25)
);
it("Normal-type attacks have no effect on Ghost-type Pokemon",
() => testMoveEffectiveness(game, Moves.TACKLE, Species.DUSCLOPS, 0)
);
it("Normal-type status moves are not affected by type matchups",
() => testMoveEffectiveness(game, Moves.GROWL, Species.DUSCLOPS, 1)
);
it("Electric-type attacks are super-effective against Water-type Pokemon",
() => testMoveEffectiveness(game, Moves.THUNDERBOLT, Species.BLASTOISE, 2)
);
it("Electric-type attacks are doubly super-effective against Water/Flying-type Pokemon",
() => testMoveEffectiveness(game, Moves.THUNDERBOLT, Species.GYARADOS, 4)
);
it("Electric-type attacks are negated by Volt Absorb",
() => testMoveEffectiveness(game, Moves.THUNDERBOLT, Species.GYARADOS, 0, Abilities.VOLT_ABSORB)
);
});

View File

@ -1,83 +0,0 @@
import { StatusEffect } from "#app/enums/status-effect.js";
import { CommandPhase } from "#app/phases/command-phase.js";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
describe("Moves - Lunar Blessing", () => {
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("double");
game.override.enemySpecies(Species.SHUCKLE);
game.override.enemyMoveset(SPLASH_ONLY);
game.override.enemyAbility(Abilities.BALL_FETCH);
game.override.moveset([Moves.LUNAR_BLESSING, Moves.SPLASH]);
game.override.ability(Abilities.BALL_FETCH);
});
it("should restore 25% HP of the user and its ally", async () => {
await game.startBattle([Species.RATTATA, Species.RATTATA]);
const [leftPlayer, rightPlayer] = game.scene.getPlayerField();
vi.spyOn(leftPlayer, "getMaxHp").mockReturnValue(100);
vi.spyOn(rightPlayer, "getMaxHp").mockReturnValue(100);
const initialHp = 1;
leftPlayer["hp"] = initialHp;
rightPlayer["hp"] = initialHp;
const expectedHeal = 25;
vi.spyOn(leftPlayer, "heal");
vi.spyOn(rightPlayer, "heal");
game.move.select(Moves.LUNAR_BLESSING, 0);
await game.phaseInterceptor.to(CommandPhase);
game.move.select(Moves.SPLASH, 1);
await game.toNextTurn();
expect(leftPlayer.heal).toHaveBeenCalledOnce();
expect(leftPlayer.heal).toHaveReturnedWith(expectedHeal);
expect(rightPlayer.heal).toHaveBeenCalledOnce();
expect(rightPlayer.heal).toHaveReturnedWith(expectedHeal);
});
it("should cure status effect of the user and its ally", async () => {
game.override.statusEffect(StatusEffect.BURN);
await game.startBattle([Species.RATTATA, Species.RATTATA]);
const [leftPlayer, rightPlayer] = game.scene.getPlayerField();
vi.spyOn(leftPlayer, "resetStatus");
vi.spyOn(rightPlayer, "resetStatus");
game.move.select(Moves.LUNAR_BLESSING, 0);
await game.phaseInterceptor.to(CommandPhase);
game.move.select(Moves.SPLASH, 1);
await game.toNextTurn();
expect(leftPlayer.resetStatus).toHaveBeenCalledOnce();
expect(rightPlayer.resetStatus).toHaveBeenCalledOnce();
expect(leftPlayer.status?.effect).toBeUndefined();
expect(rightPlayer.status?.effect).toBeUndefined();
});
});

View File

@ -1,7 +1,7 @@
import { BattlerIndex } from "#app/battle";
import { getMoveTargets } from "#app/data/move";
import { Abilities } from "#app/enums/abilities";
import { Species } from "#app/enums/species";
import * as Utils from "#app/utils";
import { TurnEndPhase } from "#app/phases/turn-end-phase";
import { Moves } from "#enums/moves";
import GameManager from "#test/utils/gameManager";
import { SPLASH_ONLY } from "#test/utils/testUtils";
@ -10,7 +10,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
const TIMEOUT = 20 * 1000;
describe("Multi-target damage reduction", () => {
describe("Moves - Multi target", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
@ -21,111 +21,160 @@ describe("Multi-target damage reduction", () => {
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
afterTrial(game);
});
beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.disableCrits()
.battleType("double")
.enemyLevel(100)
.startingLevel(100)
.enemySpecies(Species.POLIWAG)
.enemyMoveset(SPLASH_ONLY)
.enemyAbility(Abilities.BALL_FETCH)
.moveset([Moves.TACKLE, Moves.DAZZLING_GLEAM, Moves.EARTHQUAKE, Moves.SPLASH])
.ability(Abilities.BALL_FETCH);
game = beforeTrial(phaserGame);
});
it("should reduce d.gleam damage when multiple enemies but not tackle", async () => {
await game.startBattle([Species.MAGIKARP, Species.FEEBAS]);
it("2v2 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, false, false, true), TIMEOUT);
const [enemy1, enemy2] = game.scene.getEnemyField();
it("2v2 - target all near others - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, false, false, true), TIMEOUT);
game.move.select(Moves.DAZZLING_GLEAM);
game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to("MoveEndPhase");
it("2v1 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, false, true, true), TIMEOUT);
const gleam1 = enemy1.getMaxHp() - enemy1.hp;
enemy1.hp = enemy1.getMaxHp();
it("2v1 - target all near others - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, false, true, true), TIMEOUT);
await game.phaseInterceptor.to("MoveEndPhase");
it("1v2 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, true, false, true), TIMEOUT);
const tackle1 = enemy1.getMaxHp() - enemy1.hp;
enemy1.hp = enemy1.getMaxHp();
it("1v2 - target all near others - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, true, false, true), TIMEOUT);
await game.killPokemon(enemy2);
await game.toNextTurn();
it("1v1 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, true, true, false), TIMEOUT);
game.move.select(Moves.DAZZLING_GLEAM);
game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]);
it("2v2 (immune) - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, false, false, true, Abilities.LEVITATE), TIMEOUT);
await game.phaseInterceptor.to("MoveEndPhase");
it("2v2 (immune) - target all near others - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, false, false, true, Abilities.LEVITATE), TIMEOUT);
const gleam2 = enemy1.getMaxHp() - enemy1.hp;
enemy1.hp = enemy1.getMaxHp();
it("2v2 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, false, false, true), TIMEOUT);
await game.phaseInterceptor.to("MoveEndPhase");
const tackle2 = enemy1.getMaxHp() - enemy1.hp;
it("2v2 - target all near enemies - damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, false, false, true), TIMEOUT);
// Single target moves don't get reduced
expect(tackle1).toBe(tackle2);
// Moves that target all enemies get reduced if there's more than one enemy
expect(gleam1).toBeLessThanOrEqual(Utils.toDmgValue(gleam2 * 0.75) + 1);
expect(gleam1).toBeGreaterThanOrEqual(Utils.toDmgValue(gleam2 * 0.75) - 1);
}, TIMEOUT);
it("2v1 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, false, true, false), TIMEOUT);
it("should reduce earthquake when more than one pokemon other than user is not fainted", async () => {
await game.startBattle([Species.MAGIKARP, Species.FEEBAS]);
it("2v1 - target all near enemies - no damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, false, true, false), TIMEOUT);
const player2 = game.scene.getParty()[1];
const [enemy1, enemy2] = game.scene.getEnemyField();
it("1v2 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, true, false, true), TIMEOUT);
game.move.select(Moves.EARTHQUAKE);
game.move.select(Moves.SPLASH, 1);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
it("1v2 - target all near enemies - damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, true, false, true), TIMEOUT);
await game.phaseInterceptor.to("MoveEndPhase");
it("1v1 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, true, true, false), TIMEOUT);
const damagePlayer2Turn1 = player2.getMaxHp() - player2.hp;
const damageEnemy1Turn1 = enemy1.getMaxHp() - enemy1.hp;
it("2v2 (immune) - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, false, false, true, Abilities.SOUNDPROOF), TIMEOUT);
player2.hp = player2.getMaxHp();
enemy1.hp = enemy1.getMaxHp();
it("2v2 (immune) - target all near enemies - damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, false, false, true, Abilities.SOUNDPROOF), TIMEOUT);
await game.killPokemon(enemy2);
await game.toNextTurn();
game.move.select(Moves.EARTHQUAKE);
game.move.select(Moves.SPLASH, 1);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]);
await game.phaseInterceptor.to("MoveEndPhase");
const damagePlayer2Turn2 = player2.getMaxHp() - player2.hp;
const damageEnemy1Turn2 = enemy1.getMaxHp() - enemy1.hp;
enemy1.hp = enemy1.getMaxHp();
// Turn 1: 3 targets, turn 2: 2 targets
// Both should have damage reduction
expect(damageEnemy1Turn1).toBe(damageEnemy1Turn2);
expect(damagePlayer2Turn1).toBe(damagePlayer2Turn2);
await game.killPokemon(player2);
await game.toNextTurn();
game.move.select(Moves.EARTHQUAKE);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.phaseInterceptor.to("MoveEndPhase");
const damageEnemy1Turn3 = enemy1.getMaxHp() - enemy1.hp;
// Turn 3: 1 target, should be no damage reduction
expect(damageEnemy1Turn1).toBeLessThanOrEqual(Utils.toDmgValue(damageEnemy1Turn3 * 0.75) + 1);
expect(damageEnemy1Turn1).toBeGreaterThanOrEqual(Utils.toDmgValue(damageEnemy1Turn3 * 0.75) - 1);
}, TIMEOUT);
});
async function checkTargetMultiplier(game: GameManager, attackMove: Moves, killAlly: boolean, killSecondEnemy: boolean, shouldMultiplied: boolean, oppAbility?: Abilities) {
// play an attack and check target count
game.override.enemyAbility(oppAbility ? oppAbility : Abilities.BALL_FETCH);
await game.startBattle();
const playerPokemonRepr = game.scene.getPlayerField();
killAllyAndEnemy(game, killAlly, killSecondEnemy);
const targetCount = getMoveTargets(playerPokemonRepr[0], attackMove).targets.length;
const targetMultiplier = targetCount > 1 ? 0.75 : 1;
if (shouldMultiplied) {
expect(targetMultiplier).toBe(0.75);
} else {
expect(targetMultiplier).toBe(1);
}
}
async function checkDamageDecrease(game: GameManager, attackMove: Moves, killAlly: boolean, killSecondEnemy: boolean, shouldDecreased: boolean, ability?: Abilities) {
// Tested combination on first turn, 1v1 on second turn
await game.classicMode.runToSummon([Species.EEVEE, Species.EEVEE]);
if (ability !== undefined) {
game.scene.getPlayerField()[1].abilityIndex = ability;
game.scene.getEnemyField()[1].abilityIndex = ability;
}
game.move.select(Moves.SPLASH);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to(TurnEndPhase);
killAllyAndEnemy(game, killAlly, killSecondEnemy);
await game.toNextTurn();
const initialHp = game.scene.getEnemyField()[0].hp;
game.move.select(attackMove);
if (!killAlly) {
game.move.select(Moves.SPLASH, 1);
}
await game.phaseInterceptor.to(TurnEndPhase);
const afterHp = game.scene.getEnemyField()[0].hp;
killAllyAndEnemy(game, true, true);
await game.toNextTurn();
game.scene.getEnemyField()[0].hp = initialHp;
const initialHp1v1 = game.scene.getEnemyField()[0].hp;
game.move.select(attackMove);
await game.phaseInterceptor.to(TurnEndPhase);
const afterHp1v1 = game.scene.getEnemyField()[0].hp;
if (shouldDecreased) {
expect(initialHp - afterHp).toBeLessThan(0.75 * (initialHp1v1 - afterHp1v1) + 2);
expect(initialHp - afterHp).toBeGreaterThan(0.75 * (initialHp1v1 - afterHp1v1) - 2);
} else {
expect(initialHp - afterHp).toBeLessThan(initialHp1v1 - afterHp1v1 + 2);
expect(initialHp - afterHp).toBeGreaterThan(initialHp1v1 - afterHp1v1 - 2);
}
}
// To simulate the situation where all of the enemies or the player's Pokemons dies except for one.
function killAllyAndEnemy(game: GameManager, killAlly: boolean, killSecondEnemy: boolean) {
if (killAlly) {
leaveOnePlayerPokemon(game);
expect(game.scene.getPlayerField().filter(p => p.isActive()).length).toBe(1);
}
if (killSecondEnemy) {
leaveOneEnemyPokemon(game);
expect(game.scene.getEnemyField().filter(p => p.isActive()).length).toBe(1);
}
}
function leaveOnePlayerPokemon(game: GameManager) {
const playerPokemons = game.scene.getParty();
for (let i = 1; i < playerPokemons.length; i++) {
playerPokemons[i].hp = 0;
}
expect(playerPokemons.filter(pokemon => pokemon.hp > 0).length).toBe(1);
}
function leaveOneEnemyPokemon(game: GameManager) {
const enemyPokemons = game.scene.getEnemyParty();
for (let i = 1; i < enemyPokemons.length; i++) {
enemyPokemons[i].hp = 0;
}
}
function beforeTrial(phaserGame: Phaser.Game, single: boolean = false) {
const game = new GameManager(phaserGame);
game.override
.battleType("double")
.moveset([Moves.EARTHQUAKE, Moves.HYPER_VOICE, Moves.SURF, Moves.SPLASH])
.ability(Abilities.BALL_FETCH)
.passiveAbility(Abilities.UNNERVE)
.enemyMoveset(SPLASH_ONLY)
.disableCrits()
.startingLevel(50)
.enemyLevel(40)
.enemySpecies(Species.EEVEE);
return game;
}
function afterTrial(game: GameManager) {
game.phaseInterceptor.restoreOg();
}

View File

@ -62,6 +62,9 @@ describe("Moves - Tera Blast", () => {
it("increases power if user is Stellar tera type", async () => {
game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]);
const stellarTypeMultiplier = 2;
const stellarTypeDmgBonus = 20;
const basePower = moveToCheck.power;
await game.startBattle();
@ -69,25 +72,9 @@ describe("Moves - Tera Blast", () => {
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.phaseInterceptor.to("MoveEffectPhase");
expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(100);
expect(moveToCheck.calculateBattlePower).toHaveReturnedWith((basePower + stellarTypeDmgBonus) * stellarTypeMultiplier);
}, 20000);
it("is super effective against terastallized targets if user is Stellar tera type", async () => {
game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]);
await game.startBattle();
const enemyPokemon = game.scene.getEnemyPokemon()!;
vi.spyOn(enemyPokemon, "apply");
vi.spyOn(enemyPokemon, "isTerastallized").mockReturnValue(true);
game.move.select(Moves.TERA_BLAST);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.phaseInterceptor.to("MoveEffectPhase");
expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.SUPER_EFFECTIVE);
});
// Currently abilities are bugged and can't see when a move's category is changed
it.skip("uses the higher stat of the user's Atk and SpAtk for damage calculation", async () => {
game.override.enemyAbility(Abilities.TOXIC_DEBRIS);

View File

@ -1,102 +0,0 @@
import { StatusEffect } from "#app/data/status-effect";
import { Abilities } from "#app/enums/abilities";
import { EnemyPokemon } from "#app/field/pokemon";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
import { SPLASH_ONLY } from "../utils/testUtils";
const TIMEOUT = 20 * 1000;
describe("Moves - Thunder Wave", () => {
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")
.starterSpecies(Species.PIKACHU)
.moveset([Moves.THUNDER_WAVE])
.enemyMoveset(SPLASH_ONLY);
});
// References: https://bulbapedia.bulbagarden.net/wiki/Thunder_Wave_(move)
it("paralyzes non-statused Pokemon that are not Ground types", async () => {
game.override.enemySpecies(Species.MAGIKARP);
await game.startBattle();
const enemyPokemon: EnemyPokemon = game.scene.getEnemyPokemon()!;
game.move.select(Moves.THUNDER_WAVE);
await game.move.forceHit();
await game.phaseInterceptor.to("BerryPhase", false);
expect(enemyPokemon.status?.effect).toBe(StatusEffect.PARALYSIS);
}, TIMEOUT);
it("does not paralyze if the Pokemon is a Ground-type", async () => {
game.override.enemySpecies(Species.DIGLETT);
await game.startBattle();
const enemyPokemon: EnemyPokemon = game.scene.getEnemyPokemon()!;
game.move.select(Moves.THUNDER_WAVE);
await game.move.forceHit();
await game.phaseInterceptor.to("BerryPhase", false);
expect(enemyPokemon.status).toBeUndefined();
}, TIMEOUT);
it("does not paralyze if the Pokemon already has a status effect", async () => {
game.override.enemySpecies(Species.MAGIKARP).enemyStatusEffect(StatusEffect.BURN);
await game.startBattle();
const enemyPokemon: EnemyPokemon = game.scene.getEnemyPokemon()!;
game.move.select(Moves.THUNDER_WAVE);
await game.move.forceHit();
await game.phaseInterceptor.to("BerryPhase", false);
expect(enemyPokemon.status?.effect).not.toBe(StatusEffect.PARALYSIS);
}, TIMEOUT);
it("affects Ground types if the user has Normalize", async () => {
game.override.ability(Abilities.NORMALIZE).enemySpecies(Species.DIGLETT);
await game.startBattle();
const enemyPokemon: EnemyPokemon = game.scene.getEnemyPokemon()!;
game.move.select(Moves.THUNDER_WAVE);
await game.move.forceHit();
await game.phaseInterceptor.to("BerryPhase", false);
expect(enemyPokemon.status?.effect).toBe(StatusEffect.PARALYSIS);
}, TIMEOUT);
it("does not affect Ghost types if the user has Normalize", async () => {
game.override.ability(Abilities.NORMALIZE).enemySpecies(Species.HAUNTER);
await game.startBattle();
const enemyPokemon: EnemyPokemon = game.scene.getEnemyPokemon()!;
game.move.select(Moves.THUNDER_WAVE);
await game.move.forceHit();
await game.phaseInterceptor.to("BerryPhase", false);
expect(enemyPokemon.status).toBeUndefined();
}, TIMEOUT);
});

View File

@ -25,7 +25,7 @@ export default class AchvBar extends Phaser.GameObjects.Container {
}
setup(): void {
this.defaultWidth = 200;
this.defaultWidth = 160;
this.defaultHeight = 40;
this.bg = this.scene.add.nineslice(0, 0, "achv_bar", undefined, this.defaultWidth, this.defaultHeight, 41, 6, 16, 4);

View File

@ -15,16 +15,6 @@ enum Page {
VOUCHERS
}
interface LanguageSetting {
TextSize: string,
}
const languageSettings: { [key: string]: LanguageSetting } = {
"de":{
TextSize: "80px"
}
};
export default class AchvsUiHandler extends MessageUiHandler {
private readonly ROWS = 4;
private readonly COLS = 17;
@ -115,13 +105,8 @@ export default class AchvsUiHandler extends MessageUiHandler {
titleBg.setOrigin(0, 0);
this.titleText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW);
const textSize = languageSettings[i18next.language]?.TextSize ?? this.titleText.style.fontSize;
this.titleText.setFontSize(textSize);
this.titleText.setOrigin(0, 0);
const titleBgCenterX = titleBg.x + titleBg.width / 2;
const titleBgCenterY = titleBg.y + titleBg.height / 2;
this.titleText.setOrigin(0.5, 0.5);
this.titleText.setPosition(titleBgCenterX, titleBgCenterY);
this.titleText.setPositionRelative(titleBg, 8, 4);
const scoreBg = addWindow(this.scene, titleBg.x + titleBg.width, titleBg.y, 46, 24);
scoreBg.setOrigin(0, 0);

View File

@ -35,8 +35,6 @@ export default class GameChallengesUiHandler extends UiHandler {
private startCursor: Phaser.GameObjects.NineSlice;
private optionsWidth: number;
constructor(scene: BattleScene, mode: Mode | null = null) {
super(scene, mode);
}
@ -76,19 +74,18 @@ export default class GameChallengesUiHandler extends UiHandler {
// difficultyName.setOrigin(0, 0);
// difficultyName.setPositionRelative(difficultyBg, difficultyBg.width - difficultyName.displayWidth - 8, 4);
this.optionsWidth = this.scene.scaledCanvas.width * 0.6;
this.optionsBg = addWindow(this.scene, 0, headerBg.height, this.optionsWidth, this.scene.scaledCanvas.height - headerBg.height - 2);
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 9), (this.scene.game.canvas.height / 6) - headerBg.height - 2);
this.optionsBg.setName("window-options-bg");
this.optionsBg.setOrigin(0, 0);
const descriptionBg = addWindow(this.scene, 0, headerBg.height, this.scene.scaledCanvas.width - this.optionsWidth, this.scene.scaledCanvas.height - headerBg.height - 26);
const descriptionBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 18) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 26);
descriptionBg.setName("window-desc-bg");
descriptionBg.setOrigin(0, 0);
descriptionBg.setPositionRelative(this.optionsBg, this.optionsBg.width, 0);
this.descriptionText = new BBCodeText(this.scene, descriptionBg.x + 6, descriptionBg.y + 4, "", {
fontFamily: "emerald",
fontSize: 84,
fontSize: 96,
color: Color.ORANGE,
padding: {
bottom: 6
@ -112,12 +109,12 @@ export default class GameChallengesUiHandler extends UiHandler {
const startText = addTextObject(this.scene, 0, 0, i18next.t("common:start"), TextStyle.SETTINGS_LABEL);
startText.setName("text-start");
startText.setOrigin(0, 0);
startText.setPositionRelative(startBg, (startBg.width - startText.displayWidth) / 2, 4);
startText.setPositionRelative(startBg, 8, 4);
this.startCursor = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, descriptionBg.width - 8, 16, 1, 1, 1, 1);
this.startCursor = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, (this.scene.game.canvas.width / 18) - 10, 16, 1, 1, 1, 1);
this.startCursor.setName("9s-start-cursor");
this.startCursor.setOrigin(0, 0);
this.startCursor.setPositionRelative(startBg, 4, 3);
this.startCursor.setPositionRelative(startBg, 4, 4);
this.startCursor.setVisible(false);
this.valuesContainer = this.scene.add.container(0, 0);
@ -143,7 +140,7 @@ export default class GameChallengesUiHandler extends UiHandler {
};
}
this.monoTypeValue = this.scene.add.sprite(8, 98, Utils.getLocalizedSpriteKey("types"));
this.monoTypeValue = this.scene.add.sprite(8, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
this.monoTypeValue.setName("challenge-value-monotype-sprite");
this.monoTypeValue.setScale(0.86);
this.monoTypeValue.setVisible(false);
@ -358,7 +355,7 @@ export default class GameChallengesUiHandler extends UiHandler {
let ret = super.setCursor(cursor);
if (!this.cursorObj) {
this.cursorObj = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, this.optionsWidth - 8, 16, 1, 1, 1, 1);
this.cursorObj = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, (this.scene.game.canvas.width / 9) - 10, 16, 1, 1, 1, 1);
this.cursorObj.setOrigin(0, 0);
this.valuesContainer.add(this.cursorObj);
}

View File

@ -44,7 +44,7 @@ export default class FightUiHandler extends UiHandler {
this.moveInfoContainer.setName("move-info");
ui.add(this.moveInfoContainer);
this.typeIcon = this.scene.add.sprite(this.scene.scaledCanvas.width - 57, -36, Utils.getLocalizedSpriteKey("types"), "unknown");
this.typeIcon = this.scene.add.sprite(this.scene.scaledCanvas.width - 57, -36, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, "unknown");
this.typeIcon.setVisible(false);
this.moveInfoContainer.add(this.typeIcon);
@ -179,20 +179,15 @@ export default class FightUiHandler extends UiHandler {
if (hasMove) {
const pokemonMove = moveset[cursor]!; // TODO: is the bang correct?
const moveType = pokemon.getMoveType(pokemonMove.getMove());
const textureKey = Utils.getLocalizedSpriteKey("types");
this.typeIcon.setTexture(textureKey, Type[moveType].toLowerCase()).setScale(0.8);
this.typeIcon.setTexture(`types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[pokemonMove.getMove().type].toLowerCase()).setScale(0.8);
this.moveCategoryIcon.setTexture("categories", MoveCategory[pokemonMove.getMove().category].toLowerCase()).setScale(1.0);
const moveCategory = pokemonMove.getMove().category;
this.moveCategoryIcon.setTexture("categories", MoveCategory[moveCategory].toLowerCase()).setScale(1.0);
const power = pokemonMove.getMove().power;
const accuracy = pokemonMove.getMove().accuracy;
const maxPP = pokemonMove.getMovePp();
const pp = maxPP - pokemonMove.ppUsed;
const ppLeftStr = Utils.padInt(pp, 2, " ");
const ppMaxStr = Utils.padInt(maxPP, 2, " ");
this.ppText.setText(`${ppLeftStr}/${ppMaxStr}`);
this.ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`);
this.powerText.setText(`${power >= 0 ? power : "---"}`);
this.accuracyText.setText(`${accuracy >= 0 ? accuracy : "---"}`);
@ -236,7 +231,7 @@ export default class FightUiHandler extends UiHandler {
* Returns undefined if it's a status move
*/
private getEffectivenessText(pokemon: Pokemon, opponent: Pokemon, pokemonMove: PokemonMove): string | undefined {
const effectiveness = opponent.getMoveEffectiveness(pokemon, pokemonMove.getMove(), !opponent.battleData?.abilityRevealed);
const effectiveness = opponent.getMoveEffectiveness(pokemon, pokemonMove);
if (effectiveness === undefined) {
return undefined;
}
@ -279,7 +274,7 @@ export default class FightUiHandler extends UiHandler {
}
const moveColors = opponents
.map((opponent) => opponent.getMoveEffectiveness(pokemon, pokemonMove.getMove(), !opponent.battleData.abilityRevealed))
.map((opponent) => opponent.getMoveEffectiveness(pokemon, pokemonMove))
.sort((a, b) => b - a)
.map((effectiveness) => getTypeDamageMultiplierColor(effectiveness ?? 0, "offense"));

View File

@ -410,7 +410,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (index === 0 || index === 19) {
return;
}
const typeSprite = this.scene.add.sprite(0, 0, Utils.getLocalizedSpriteKey("types"));
const typeSprite = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
typeSprite.setScale(0.5);
typeSprite.setFrame(type.toLowerCase());
typeOptions.push(new DropDownOption(this.scene, index, new DropDownLabel("", typeSprite)));
@ -668,12 +668,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonSprite.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true });
this.starterSelectContainer.add(this.pokemonSprite);
this.type1Icon = this.scene.add.sprite(8, 98, Utils.getLocalizedSpriteKey("types"));
this.type1Icon = this.scene.add.sprite(8, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
this.type1Icon.setScale(0.5);
this.type1Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type1Icon);
this.type2Icon = this.scene.add.sprite(26, 98, Utils.getLocalizedSpriteKey("types"));
this.type2Icon = this.scene.add.sprite(26, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
this.type2Icon.setScale(0.5);
this.type2Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type2Icon);

View File

@ -716,8 +716,7 @@ export default class SummaryUiHandler extends UiHandler {
const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => {
const xCoord = typeLabel.width * typeLabel.scale + 9 + 34 * index;
const typeIcon = !tera
? this.scene.add.sprite(xCoord, 42, Utils.getLocalizedSpriteKey("types"), Type[type].toLowerCase())
: this.scene.add.sprite(xCoord, 42, "type_tera");
? this.scene.add.sprite(xCoord, 42, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[type].toLowerCase()) : this.scene.add.sprite(xCoord, 42, "type_tera");
if (tera) {
typeIcon.setScale(0.5);
const typeRgb = getTypeRgb(type);
@ -935,14 +934,10 @@ export default class SummaryUiHandler extends UiHandler {
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.extraMoveRowContainer.setVisible(true);
const newMoveTypeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[this.newMove?.type!].toLowerCase()); // TODO: is this bang correct?
newMoveTypeIcon.setOrigin(0, 1);
this.extraMoveRowContainer.add(newMoveTypeIcon);
if (this.newMove && this.pokemon) {
const spriteKey = Utils.getLocalizedSpriteKey("types");
const moveType = this.pokemon.getMoveType(this.newMove);
const newMoveTypeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase());
newMoveTypeIcon.setOrigin(0, 1);
this.extraMoveRowContainer.add(newMoveTypeIcon);
}
const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp");
ppOverlay.setOrigin(0, 1);
this.extraMoveRowContainer.add(ppOverlay);
@ -961,11 +956,8 @@ export default class SummaryUiHandler extends UiHandler {
const moveRowContainer = this.scene.add.container(0, 16 * m);
this.moveRowsContainer.add(moveRowContainer);
if (move && this.pokemon) {
const spriteKey = Utils.getLocalizedSpriteKey("types");
const moveType = this.pokemon.getMoveType(move.getMove());
const typeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase());
typeIcon.setOrigin(0, 1);
if (move) {
const typeIcon = this.scene.add.sprite(0, 0, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[move.getMove().type].toLowerCase()); typeIcon.setOrigin(0, 1);
moveRowContainer.add(typeIcon);
}

View File

@ -574,12 +574,3 @@ export function isNullOrUndefined(object: any): boolean {
export function toDmgValue(value: number, minValue: number = 1) {
return Math.max(Math.floor(value), minValue);
}
/**
* Helper method to localize a sprite key (e.g. for types)
* @param baseKey the base key of the sprite (e.g. `type`)
* @returns the localized sprite key
*/
export function getLocalizedSpriteKey(baseKey: string) {
return `${baseKey}${verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`;
}