Compare commits

...

12 Commits

Author SHA1 Message Date
innerthunder
0221c9faba
[Ability][Move] Rewrite Type Resolution and Effectiveness Calculation Functions (#3704)
* Make type/category read-only

* Fix protean/libero tests

* Refactor Pokemon type effectiveness calculation

* Merge getMoveEffectiveness and getAttackMoveEffectiveness

* Move priority-blocking ability check

* Fix incorrect early stopping implementation in MultiHitAttr

* Fix Aerilate, etc. affecting variable-type moves

* Thunder Wave now respects Attack type immunities

* Use final move types for pre-defend abilities

* Steal some things from flx's PR hehe

* Fix Thousand Arrows + "No effect" messages

* Fix status type effectiveness check

* Another status move effectiveness update + some docs

* changing status logic again...

* Fix unnecessary "No Effect" message for Volt Absorb, etc

* Add type effectiveness unit test

* Add Galvanize integration tests

* Add multi-hit test to galvanize tests

* Add power check to first Galvanize test

* Add missing doc line

Co-authored-by: Amani H. <109637146+xsn34kzx@users.noreply.github.com>

* Resolve torranx's nits

* Apply suggestions from Kev's code review

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* More suggestions I missed

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Optimize effectiveness test and make others more stylish (#3)

* Resolve Kev's remaining nits and some test issues

---------

Co-authored-by: Amani H. <109637146+xsn34kzx@users.noreply.github.com>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: flx-sta
Co-authored-by: frutescens
2024-08-25 19:11:01 -07:00
NightKev
443e4bd24c
Multi-target damage reduction is now properly calculated (#3734) 2024-08-25 17:40:43 -07:00
Leo Kim
387d3ac999
[Enhancement] Slightly improve the challenge selection UI, achievement UI, and achievement message window. (#3731)
* resize achv box default width

* add language font size option. DE font size 80px

* resize challenge desc window width. fix cursor width. shrink font size of desc. set middle align start label
2024-08-25 17:11:03 -07:00
Blitzy
0bdb23d41f
[Balance] Give Partner Eevee and G-Max Eevee access to their signatures / Fix G-Max Pikachu Learnset (#2474)
* Add Moves to Eevee

* Add Level Up Moves to G-Max Eevee

* Fix Pikachu G-Max Learnset
2024-08-25 15:26:19 -07:00
damocleas
b7d71df466
[Balance] Gigantamax State/Form Rebalance (#2442)
* [Balance] Gigantamax State/Form Rebalance (WIP)

* GMAX Ability for Orbeetle adjusted

* fixed typo on CHLOROPHYLL

* Adjusted stats so there was a less intense drop in some stats

* Added comments to GMAX Pikachu, Eevee, Meowth

* Updated ability for GMAX Kingler and Eevee

* Added Stellar typing to GMAX Eevee

* Fixed typing on GMAX Eevee and Snorlax

* GMax Garbodor- Toxic Debris > Corrosion

* Corrected Trubbish passive to not overlap with GMax Garbodor

* Update pokemonFixed Coalossal, Flapple, and Centiskorch BST, Alcremie Ability Change

* Changed Alcremie Passive in adjustment with Gmax ability

* Undid Eevee being Stellar

* Gmax Sandaconda Sand Stream -> Sand Spit

* Balance Sweep of changes by damo, less dropped stats and simpler spreads

* fixed 5 Appletun BST I missed

* fixed missing Hatterene BST
2024-08-25 22:51:00 +02:00
Asdar
1c715d74b1
[Localisation] [IT] Old PRs to .json and screenshots (#3737)
* [Localisation] Italian PRs to .json and screenshots

* Update src/locales/it/trainer-titles.json

Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>

---------

Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>
2024-08-25 13:44:08 -07:00
Lugiad
6b11632114
[Localization] Some French corrections + new dialogues translations (#3727)
* Update ability-trigger.json

* Update ability.json

* Update achv-female.json

* Update achv-male.json

* Update battle-info.json

* Update bgm-name.json

* Update egg.json

* Update menu.json

* Update modifier-type.json

* Update modifier.json

* Update modifier.json

* Update trainer-classes.json

* Update move.json

* Update dialogue-male.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-double-battle-female.json

* Update dialogue-double-battle-male.json

* Update dialogue-male.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update bgm-name.json

* Update bgm-name.json

* Update move.json

* Update bgm-name.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-male.json

* Update dialogue-male.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update modifier.json

* Update dialogue-male.json

* Update dialogue-female.json

* Update dialogue-male.json

* Update dialogue-female.json
2024-08-25 22:09:01 +02:00
gitlocalize-app[bot]
3bcc9f76f1
Translate modifier-type.json via GitLocalize (#3758)
Co-authored-by: Asdar <asdargmng@gmail.com>
2024-08-25 22:06:36 +02:00
schmidtc1
93f658b624
[Bug] Fixes Lunar Blessing only healing twice on the user instead of ally (#3701)
* Sets Lunar Blessing selfTarget healing to false

* Removes redundant lines

* Adds unit test for Lunar Blessing

* Adjusts unit tests to spy on function calls
2024-08-26 03:58:28 +08:00
NightKev
4162762a0e
[Test] Refactor/consolidate Forecast tests (#3754) 2024-08-25 12:24:44 -07:00
gitlocalize-app[bot]
4ac726f79e
Translate menu.json via GitLocalize (#3752)
Co-authored-by: Asdar <asdargmng@gmail.com>
2024-08-25 12:19:32 -07:00
Blitzy
96a404a3d5
[Balance] Revert Zippy Zap back to its LGPE Implementation (#3495)
* Update move.ts

* Update Move Description

* Update move.ts

---------

Co-authored-by: xsn34kzx <xsn34kzx@gmail.com>
2024-08-25 11:35:58 -07:00
52 changed files with 1808 additions and 1053 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 } 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, NeutralDamageAgainstFlyingTypeMultiplierAttr } 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 && move.type === this.immuneType) {
if (attacker !== pokemon && attacker.getMoveType(move) === this.immuneType) {
(args[0] as Utils.NumberHolder).value = 0;
return true;
}
@ -372,7 +372,8 @@ export class AttackTypeImmunityAbAttr extends TypeImmunityAbAttr {
* Example: Levitate
*/
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (move.category !== MoveCategory.STATUS) {
// 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)) {
return super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args);
}
return false;
@ -392,6 +393,7 @@ 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;
}
@ -415,7 +417,7 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr {
const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args);
if (ret) {
cancelled.value = true;
cancelled.value = true; // Suppresses "No Effect" message
if (!simulated) {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels));
}
@ -440,7 +442,7 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr {
const ret = super.applyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args);
if (ret) {
cancelled.value = true;
cancelled.value = true; // Suppresses "No Effect" message
if (!simulated) {
pokemon.addTag(this.tagType, this.turnCount, undefined, pokemon.id);
}
@ -456,8 +458,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(move.type, attacker) < 2) {
cancelled.value = true;
if (move instanceof AttackMove && pokemon.getAttackTypeEffectiveness(pokemon.getMoveType(move), attacker) < 2) {
cancelled.value = true; // Suppresses "No Effect" message
(args[0] as Utils.NumberHolder).value = 0;
return true;
}
@ -764,7 +766,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
if (simulated) {
return true;
}
const type = move.type;
const type = attacker.getMoveType(move);
const pokemonTypes = pokemon.getTypes(true);
if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) {
pokemon.summonData.types = [ type ];
@ -1212,7 +1214,7 @@ export class FieldMultiplyBattleStatAbAttr extends AbAttr {
}
export class MoveTypeChangeAttr extends PreAttackAbAttr {
export class MoveTypeChangeAbAttr extends PreAttackAbAttr {
constructor(
private newType: Type,
private powerMultiplier: number,
@ -1221,11 +1223,14 @@ export class MoveTypeChangeAttr 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.powerMultiplier;
args[0].value = this.newType;
}
if (args[1] && args[1] instanceof Utils.NumberHolder) {
args[1].value *= this.powerMultiplier;
}
return true;
}
@ -1257,22 +1262,12 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
attr instanceof CopyMoveAttr
)
) {
// 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;
const moveType = pokemon.getMoveType(move);
// 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 (pokemon.getTypes().some((t) => t !== moveType)) {
if (!simulated) {
this.moveType = moveCopy.type;
pokemon.summonData.types = [moveCopy.type];
this.moveType = moveType;
pokemon.summonData.types = [moveType];
pokemon.updateInfo();
}
@ -2978,16 +2973,20 @@ function getAnticipationCondition(): AbAttrCondition {
return (pokemon: Pokemon) => {
for (const opponent of pokemon.getOpponents()) {
for (const move of opponent.moveset) {
// move is super effective
if (move!.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move!.getMove().type, opponent, true) >= 2) { // TODO: is this bang correct?
// 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) {
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
@ -5019,7 +5018,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(MoveTypeChangeAttr, Type.NORMAL, 1.2, (user, target, move) => {
.attr(MoveTypeChangeAbAttr, 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)
@ -5260,7 +5259,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(MoveTypeChangeAttr, Type.ICE, 1.2, (user, target, move) => move.type === Type.NORMAL),
.attr(MoveTypeChangeAbAttr, Type.ICE, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
new Ability(Abilities.SWEET_VEIL, 6)
.attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.SLEEP)
.attr(UserFieldBattlerTagImmunityAbAttr, BattlerTagType.DROWSY)
@ -5283,11 +5282,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(MoveTypeChangeAttr, Type.FAIRY, 1.2, (user, target, move) => move.type === Type.NORMAL),
.attr(MoveTypeChangeAbAttr, Type.FAIRY, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
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(MoveTypeChangeAttr, Type.FLYING, 1.2, (user, target, move) => move.type === Type.NORMAL),
.attr(MoveTypeChangeAbAttr, Type.FLYING, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
new Ability(Abilities.PARENTAL_BOND, 6)
.attr(AddSecondStrikeAbAttr, 0.25),
new Ability(Abilities.DARK_AURA, 6)
@ -5359,11 +5358,11 @@ export function initAbilities() {
new Ability(Abilities.LONG_REACH, 7)
.attr(IgnoreContactAbAttr),
new Ability(Abilities.LIQUID_VOICE, 7)
.attr(MoveTypeChangeAttr, Type.WATER, 1, (user, target, move) => move.hasFlag(MoveFlags.SOUND_BASED)),
.attr(MoveTypeChangeAbAttr, 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(MoveTypeChangeAttr, Type.ELECTRIC, 1.2, (user, target, move) => move.type === Type.NORMAL),
.attr(MoveTypeChangeAbAttr, Type.ELECTRIC, 1.2, (user, target, move) => move.type === Type.NORMAL && !move.hasAttr(VariableMoveTypeAttr)),
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, MoveTypeChangeAttr, 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, MoveTypeChangeAbAttr, 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,9 +113,8 @@ type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean;
export default class Move implements Localizable {
public id: Moves;
public name: string;
public type: Type;
public defaultType: Type;
public category: MoveCategory;
private _type: Type;
private _category: MoveCategory;
public moveTarget: MoveTarget;
public power: integer;
public accuracy: integer;
@ -133,9 +132,8 @@ export default class Move implements Localizable {
this.id = id;
this.nameAppend = "";
this.type = type;
this.defaultType = type;
this.category = category;
this._type = type;
this._category = category;
this.moveTarget = defaultMoveTarget;
this.power = power;
this.accuracy = accuracy;
@ -158,6 +156,13 @@ 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;
@ -733,7 +738,7 @@ export default class Move implements Localizable {
const power = new Utils.NumberHolder(this.power);
const typeChangeMovePowerMultiplier = new Utils.NumberHolder(1);
applyPreAttackAbAttrs(MoveTypeChangeAttr, source, target, this, simulated, typeChangeMovePowerMultiplier);
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, source, target, this, true, null, 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)) {
@ -1083,15 +1088,12 @@ export class PreMoveMessageAttr extends MoveAttr {
}
}
export class StatusMoveTypeImmunityAttr extends MoveAttr {
public immuneType: Type;
constructor(immuneType: Type) {
super(false);
this.immuneType = immuneType;
}
}
/**
* 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 IgnoreOpponentStatChangesAttr extends MoveAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
@ -1851,19 +1853,11 @@ export class MultiHitAttr extends MoveAttr {
* @returns True
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
let hitTimes: integer;
const hitType = new Utils.NumberHolder(this.multiHitType);
applyMoveAttrs(ChangeMultiHitTypeAttr, user, target, move, hitType);
this.multiHitType = hitType.value;
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;
(args[0] as Utils.NumberHolder).value = this.getHitCount(user, target);
return true;
}
@ -3762,7 +3756,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.IntegerHolder);
const category = (args[0] as Utils.NumberHolder);
if (user.getBattleStat(Stat.ATK, target, move) > user.getBattleStat(Stat.SPATK, target, move)) {
category.value = MoveCategory.PHYSICAL;
@ -3775,7 +3769,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.IntegerHolder);
const category = (args[0] as Utils.NumberHolder);
if (user.isTerastallized() && user.getBattleStat(Stat.ATK, target, move) > user.getBattleStat(Stat.SPATK, target, move)) {
category.value = MoveCategory.PHYSICAL;
@ -3791,18 +3785,21 @@ export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr {
* @extends VariablePowerAttr
*/
export class TeraBlastPowerAttr extends VariablePowerAttr {
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
* 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 {
const power = args[0] as Utils.NumberHolder;
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;
if (user.isTerastallized() && user.getTeraType() === Type.STELLAR) {
power.value = 100;
return true;
}
@ -3862,10 +3859,15 @@ 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?
move.type = Type[Type[form]];
moveType.value = Type[Type[form]];
return true;
}
@ -3875,24 +3877,29 @@ 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
move.type = Type.ELECTRIC;
moveType.value = Type.ELECTRIC;
break;
case 2: // Burn Drive
move.type = Type.FIRE;
moveType.value = Type.FIRE;
break;
case 3: // Chill Drive
move.type = Type.ICE;
moveType.value = Type.ICE;
break;
case 4: // Douse Drive
move.type = Type.WATER;
moveType.value = Type.WATER;
break;
default:
move.type = Type.NORMAL;
moveType.value = Type.NORMAL;
break;
}
return true;
@ -3904,15 +3911,20 @@ 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
move.type = Type.DARK;
moveType.value = Type.DARK;
break;
default: // Full Belly Mode
move.type = Type.ELECTRIC;
moveType.value = Type.ELECTRIC;
break;
}
return true;
@ -3924,18 +3936,23 @@ 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
move.type = Type.FIRE;
moveType.value = Type.FIRE;
break;
case 2: // Aqua breed
move.type = Type.WATER;
moveType.value = Type.WATER;
break;
default:
move.type = Type.FIGHTING;
moveType.value = Type.FIGHTING;
break;
}
return true;
@ -3947,25 +3964,30 @@ 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
move.type = Type.WATER;
moveType.value = Type.WATER;
break;
case 2: // Hearthflame Mask
case 6: // Hearthflame Mask Tera
move.type = Type.FIRE;
moveType.value = Type.FIRE;
break;
case 3: // Cornerstone Mask
case 7: // Cornerstone Mask Tera
move.type = Type.ROCK;
moveType.value = Type.ROCK;
break;
case 4: // Teal Mask Tera
default:
move.type = Type.GRASS;
moveType.value = Type.GRASS;
break;
}
return true;
@ -3977,22 +3999,27 @@ 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:
move.type = Type.FIRE;
moveType.value = Type.FIRE;
break;
case WeatherType.RAIN:
case WeatherType.HEAVY_RAIN:
move.type = Type.WATER;
moveType.value = Type.WATER;
break;
case WeatherType.SANDSTORM:
move.type = Type.ROCK;
moveType.value = Type.ROCK;
break;
case WeatherType.HAIL:
case WeatherType.SNOW:
move.type = Type.ICE;
moveType.value = Type.ICE;
break;
default:
return false;
@ -4015,10 +4042,15 @@ 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.IntegerHolder} The move's type to be modified
* @param args [0] {@linkcode Utils.NumberHolder} 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;
}
@ -4026,16 +4058,16 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
const currentTerrain = user.scene.arena.getTerrainType();
switch (currentTerrain) {
case TerrainType.MISTY:
move.type = Type.FAIRY;
moveType.value = Type.FAIRY;
break;
case TerrainType.ELECTRIC:
move.type = Type.ELECTRIC;
moveType.value = Type.ELECTRIC;
break;
case TerrainType.GRASSY:
move.type = Type.GRASS;
moveType.value = Type.GRASS;
break;
case TerrainType.PSYCHIC:
move.type = Type.PSYCHIC;
moveType.value = Type.PSYCHIC;
break;
default:
return false;
@ -4044,8 +4076,17 @@ 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
@ -4053,7 +4094,7 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
+(user.ivs[Stat.SPATK] & 1) * 16
+(user.ivs[Stat.SPDEF] & 1) * 32) * 15/63);
move.type = [
moveType.value = [
Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND,
Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL,
Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC,
@ -4068,16 +4109,21 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
* @extends VariableMoveTypeAttr
*/
export class TeraBlastTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
/**
* @param user {@linkcode Pokemon} the user's type is checked
* @param user {@linkcode Pokemon} the user of the move
* @param target {@linkcode Pokemon} N/A
* @param move {@linkcode Move} {@linkcode Move.TeraBlastTypeAttr}
* @param {any[]} args N/A
* @returns true or false
* @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;
}
if (user.isTerastallized()) {
move.type = user.getTeraType(); //changes move type to tera type
moveType.value = user.getTeraType(); // changes move type to tera type
return true;
}
@ -4087,14 +4133,18 @@ 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();
move.type = nonTeraTypes[0];
moveType.value = nonTeraTypes[0];
return true;
} else if (userTypes.length > 0) {
move.type = userTypes[0];
moveType.value = userTypes[0];
return true;
} else {
return false;
@ -4113,8 +4163,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. Levitating pokemon are instantly affected by typing
if (target.isOfType(Type.FLYING) || target.hasAbility(Abilities.LEVITATE)) {
//When a flying type is hit, the first hit is always 1x multiplier.
if (target.isOfType(Type.FLYING)) {
multiplier.value = 1;
}
return true;
@ -6505,7 +6555,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(StatusMoveTypeImmunityAttr, Type.GROUND),
.attr(RespectAttackTypeImmunityAttr),
new AttackMove(Moves.THUNDER, Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, 30, 0, 1)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
.attr(ThunderAccuracyAttr)
@ -8345,8 +8395,8 @@ export function initMoves() {
.partial()
.ignoresVirtual(),
/* End Unused */
new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 100, 2, 7)
.attr(StatChangeAttr, BattleStat.EVA, 1, true),
new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 50, 100, 15, 100, 2, 7) //LGPE Implementation
.attr(CritOnlyAttr),
new AttackMove(Moves.SPLISHY_SPLASH, Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, 30, 0, 7)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS)
.target(MoveTarget.ALL_NEAR_ENEMIES),
@ -8632,7 +8682,6 @@ 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)
@ -8736,8 +8785,7 @@ 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)
.attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP)
.attr(HealAttr, 0.25, true, false)
.attr(HealStatusEffectAttr, false, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN, StatusEffect.SLEEP)
.target(MoveTarget.USER_AND_ALLIES)
.triageMove(),

View File

@ -18800,6 +18800,85 @@ 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.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 625, 100, 90, 120, 110, 130, 75, 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 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.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 634, 98, 100, 96, 135, 110, 95, 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 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, null, 25, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 630, 100, 95, 130, 105, 125, 75, 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 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.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 495, 75, 50, 75, 120, 100, 75, 45, 50, 198, 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 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.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 420, 45, 60, 65, 100, 75, 75, 190, 50, 112),
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 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.PICKUP, Abilities.TECHNICIAN, Abilities.UNNERVE, 390, 50, 85, 60, 70, 50, 75, 255, 50, 58),
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 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.NO_GUARD, Abilities.STEADFAST, 605, 113, 170, 90, 70, 95, 67, 45, 50, 253),
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 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.NONE, Abilities.NONE, 600, 75, 95, 85, 160, 95, 90, 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 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.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 575, 70, 165, 145, 60, 70, 65, 60, 50, 166),
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 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.WATER_ABSORB, Abilities.SHELL_ARMOR, Abilities.HYDRATION, 635, 160, 95, 110, 95, 125, 50, 45, 50, 187),
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 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.RUN_AWAY, Abilities.ADAPTABILITY, Abilities.ANTICIPATION, 425, 70, 75, 80, 60, 95, 45, 45, 50, 65),
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 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, null, 35, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 640, 200, 130, 85, 75, 130, 20, 25, 50, 189),
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 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, null, 21, 107.3, Abilities.STENCH, Abilities.WEAK_ARMOR, Abilities.AFTERMATH, 574, 100, 125, 102, 80, 102, 65, 60, 50, 166),
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 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.NONE, Abilities.NONE, 700, 170, 165, 165, 95, 75, 30, 3, 0, 300),
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 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.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 630, 125, 150, 115, 75, 90, 75, 45, 50, 265),
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 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.BLAZE, Abilities.NONE, Abilities.LIBERO, 630, 100, 145, 90, 75, 90, 130, 45, 50, 265),
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 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.TORRENT, Abilities.NONE, Abilities.SNIPER, 630, 90, 100, 90, 150, 90, 110, 45, 50, 265),
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 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.PRESSURE, Abilities.UNNERVE, Abilities.MIRROR_ARMOR, 595, 125, 100, 135, 60, 95, 80, 45, 50, 248),
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 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.SWARM, Abilities.FRISK, Abilities.TELEPATHY, 605, 75, 50, 140, 90, 150, 100, 45, 50, 253),
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 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.SHELL_ARMOR, Abilities.SWIFT_SWIM, 585, 115, 150, 110, 55, 85, 70, 75, 50, 170),
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 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.FLAME_BODY, Abilities.FLASH_FIRE, 610, 140, 95, 150, 95, 105, 25, 45, 50, 255),
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 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.RIPEN, Abilities.GLUTTONY, Abilities.HUSTLE, 585, 90, 140, 90, 120, 75, 70, 45, 50, 170),
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 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.RIPEN, Abilities.GLUTTONY, Abilities.THICK_FAT, 585, 140, 95, 95, 135, 95, 25, 45, 50, 170),
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 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.SHED_SKIN, Abilities.SAND_VEIL, 610, 90, 135, 150, 75, 80, 80, 120, 50, 179),
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 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.MINUS, Abilities.TECHNICIAN, 602, 95, 118, 80, 144, 80, 85, 45, 50, 176),
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 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.WHITE_SMOKE, Abilities.FLAME_BODY, 625, 125, 145, 75, 105, 105, 70, 75, 50, 184),
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 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.HEALER, Abilities.ANTICIPATION, Abilities.MAGIC_BOUNCE, 610, 70, 105, 110, 160, 125, 40, 45, 50, 255),
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 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.FRISK, Abilities.PICKPOCKET, 610, 120, 155, 75, 110, 85, 65, 45, 50, 255),
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 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.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 595, 85, 70, 85, 140, 150, 65, 100, 50, 173),
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 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, null, 23, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 600, 150, 160, 80, 90, 80, 40, 90, 50, 175),
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 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.LIGHT_METAL, Abilities.HEAVY_METAL, Abilities.STALWART, 635, 90, 110, 145, 140, 60, 90, 45, 50, 187),
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 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, 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 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 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.TOXIC_DEBRIS,
[Species.TRUBBISH]: Abilities.NEUTRALIZING_GAS,
[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.MISTY_SURGE,
[Species.MILCERY]: Abilities.REGENERATOR,
[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, StatusMoveTypeImmunityAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, NeutralDamageAgainstFlyingTypeMultiplierAttr, OneHitKOAccuracyAttr } from "../data/move";
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 { 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 } 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, MoveTypeChangeAbAttr } from "../data/ability";
import PokemonData from "../system/pokemon-data";
import { BattlerIndex } from "../battle";
import { Mode } from "../ui/ui";
@ -1208,60 +1208,83 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
/**
* Calculates the effectiveness of a move against the Pokémon.
*
* @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
* 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
*/
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier {
if (move.getMove().category === MoveCategory.STATUS) {
return 1;
}
getMoveType(move: Move, simulated: boolean = true): Type {
const moveTypeHolder = new Utils.NumberHolder(move.type);
return this.getAttackMoveEffectiveness(source, move, !this.battleData?.abilityRevealed);
applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder);
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder);
return moveTypeHolder.value as Type;
}
/**
* Calculates the effectiveness of an attack move against the Pokémon.
* Calculates the effectiveness of a 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.
* @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
*/
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 (!typeless && !ignoreAbility) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier);
getMoveEffectiveness(source: Pokemon, move: Move, ignoreAbility: boolean = false, simulated: boolean = true, cancelled?: Utils.BooleanHolder): TypeDamageMultiplier {
if (move.hasAttr(TypelessAttr)) {
return 1;
}
if (!cancelled.value && !ignoreAbility) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, true, typeMultiplier);
const moveType = source.getMoveType(move);
const typeMultiplier = new Utils.NumberHolder((move.category !== MoveCategory.STATUS || move.hasAttr(RespectAttackTypeImmunityAttr))
? this.getAttackTypeEffectiveness(moveType, source, false, simulated)
: 1);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
if (this.getTypes().find(t => move.isTypeImmune(source, this, t))) {
typeMultiplier.value = 0;
}
return (!cancelled.value ? Number(typeMultiplier.value) : 0) as TypeDamageMultiplier;
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;
}
/**
* Calculates the type effectiveness multiplier for an attack type
* @param moveOrType The move being used, or a type if the move is unknown
* @param source the Pokemon using the move
* @param moveType {@linkcode Type} the type of the move being used
* @param source {@linkcode Pokemon} 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(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;
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier {
if (moveType === Type.STELLAR) {
return this.isTerastallized() ? 2 : 1;
}
@ -1281,7 +1304,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, false, moveType, defType);
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType);
}
if (ignoreImmunity.value) {
return 1;
@ -1303,15 +1326,6 @@ 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;
}
@ -1959,29 +1973,23 @@ 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.IntegerHolder(move.category);
const variableCategory = new Utils.NumberHolder(move.category);
applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory);
const moveCategory = variableCategory.value as MoveCategory;
applyMoveAttrs(VariableMoveTypeAttr, source, this, move);
const types = this.getTypes(true, true);
/** The move's type after type-changing effects are applied */
const moveType = source.getMoveType(move);
/** 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);
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;
}
/**
* 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);
switch (moveCategory) {
case MoveCategory.PHYSICAL:
@ -1989,27 +1997,44 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const isPhysical = moveCategory === MoveCategory.PHYSICAL;
const sourceTeraType = source.getTeraType();
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));
}
const power = move.calculateBattlePower(source, this);
if (cancelled.value) {
// Cancelled moves fail silently
source.stopMultiHit(this);
result = HitResult.NO_EFFECT;
return HitResult.NO_EFFECT;
} else {
const typeBoost = source.findTag(t => t instanceof TypeBoostTag && t.boostedType === move.type) as TypeBoostTag;
const typeBoost = source.findTag(t => t instanceof TypeBoostTag && t.boostedType === moveType) as TypeBoostTag;
if (typeBoost?.oneUse) {
source.removeTag(typeBoost.tagType);
}
const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(move.type, source.isGrounded()));
/** Combined damage multiplier from field effects such as weather, terrain, etc. */
const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(moveType, 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;
@ -2059,13 +2084,12 @@ 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] === move.type || (sourceTypes.length > 1 && sourceTypes[1] === move.type);
const matchesSourceType = sourceTypes[0] === moveType || (sourceTypes.length > 1 && sourceTypes[1] === moveType);
const stabMultiplier = new Utils.NumberHolder(1);
if (sourceTeraType === Type.UNKNOWN && matchesSourceType) {
stabMultiplier.value += 0.5;
} else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === move.type) {
} else if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === moveType) {
stabMultiplier.value += 0.5;
}
@ -2075,8 +2099,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
stabMultiplier.value = Math.min(stabMultiplier.value + 0.5, 2.25);
}
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)
// 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;
applyMoveAttrs(VariableAtkAttr, source, this, move, sourceAtk);
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
@ -2094,7 +2119,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.value
* typeMultiplier
* arenaAttackTypeMultiplier.value
* screenMultiplier.value
* twoStrikeMultiplier.value
@ -2128,7 +2153,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
});
}
if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && move.type === Type.DRAGON) {
if (this.scene.arena.terrain?.terrainType === TerrainType.MISTY && this.isGrounded() && moveType === Type.DRAGON) {
damage.value = Utils.toDmgValue(damage.value / 2);
}
@ -2142,22 +2167,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
result = result!; // telling TS compiler that result is defined!
if (!result) {
if (!typeMultiplier.value) {
result = move.id === Moves.SHEER_COLD ? HitResult.IMMUNE : HitResult.NO_EFFECT;
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;
} else {
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;
}
result = HitResult.NOT_VERY_EFFECTIVE;
}
}
@ -2224,15 +2245,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
case HitResult.NOT_VERY_EFFECTIVE:
this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective"));
break;
case HitResult.NO_EFFECT:
this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) }));
break;
case HitResult.IMMUNE:
this.scene.queueMessage(i18next.t("battle:hitResultImmune", { pokemonName: this.name }));
break;
case HitResult.ONE_HIT_KO:
this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO"));
break;
case HitResult.IMMUNE:
case HitResult.NO_EFFECT:
console.error("Unhandled move immunity!");
break;
}
}
@ -2244,23 +2263,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
if (damage) {
const attacker = this.scene.getPokemonById(source.id)!; // TODO: is this bang correct?
destinyTag?.lapse(attacker, BattlerTagLapseType.CUSTOM);
destinyTag?.lapse(source, BattlerTagLapseType.CUSTOM);
}
}
break;
case MoveCategory.STATUS:
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) {
if (!cancelled.value && typeMultiplier === 0) {
this.scene.queueMessage(i18next.t("battle:hitResultNoEffect", { pokemonName: getPokemonNameWithAffix(this) }));
}
result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS;
result = (typeMultiplier === 0) ? HitResult.NO_EFFECT : HitResult.STATUS;
break;
}
@ -3917,7 +3928,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.getAttackMoveEffectiveness(this, pokemonMove);
const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed);
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 raises the user's evasiveness."
"effect": "The user attacks the target with bursts of electricity at high speed. This move always goes first and results in a critical hit."
},
"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": "Contraseña debe tener 6 o más caracter.",
"invalidRegisterPassword": "La contraseña debe tener 6 o más caracteres.",
"usernameAlreadyUsed": "El usuario ya está en uso",
"accountNonExistent": "El usuario no existe",
"unmatchingPassword": "La contraseña no coincide",
@ -37,12 +37,19 @@
"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.",
"errorServerDown": "¡Ups! Ha habido un problema al contactar con el servidor.\n\nPuedes mantener esta ventana abierta,\nel 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.",
"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."
}

View File

@ -97,6 +97,10 @@
"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."
},
@ -129,12 +133,12 @@
"name": "Caramelorarísimo"
},
"MEGA_BRACELET": {
"name": "Mega-aro",
"description": "Las Megapiedras están disponibles."
"name": "Megapulsera",
"description": "Las megapiedras se vuelven disponibles."
},
"DYNAMAX_BAND": {
"name": "Maximuñequera",
"description": "Las Maxisetas están disponibles."
"description": "Las maxisetas se vuelven disponibles."
},
"TERA_ORB": {
"name": "Orbe Teracristal",
@ -154,42 +158,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": "Cen. Sagrada"
"name": "Ceniza 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": "White Herb",
"description": "An item to be held by a Pokémon. It will restore any lowered stat in battle."
"name": "Hierba blanca",
"description": "Un objeto que puede llevar un Pokémon. Restaurará cualquier estadística reducida en combate."
},
"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"
@ -204,10 +208,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": {
@ -215,8 +219,8 @@
"description": "Los que no combatan reciben el 20% de la EXP."
},
"EXP_BALANCE": {
"name": "Equilibrar EXP",
"description": "Da mayor parte de la EXP recibida a los miembros del equipo que tengan menos nivel."
"name": "Equilibrador EXP",
"description": "Da una mayor parte de la EXP recibida a los miembros del equipo que tengan menos nivel."
},
"OVAL_CHARM": {
"name": "Amuleto Oval",
@ -232,13 +236,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",
@ -249,7 +253,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": {
@ -266,7 +270,7 @@
"name": "Real de oro"
},
"AMULET_COIN": {
"name": "Moneda Amuleto",
"name": "Moneda amuleto",
"description": "Aumenta el dinero ganado en un 20%."
},
"GOLDEN_PUNCH": {
@ -279,10 +283,10 @@
},
"LOCK_CAPSULE": {
"name": "Cápsula candado",
"description": "Le permite bloquear las rarezas de los objetos al cambiar de objetos."
"description": "Permite bloquear las rarezas de los objetos al refrescar objetos."
},
"GRIP_CLAW": {
"name": "Garra Garfio"
"name": "Garra garfio"
},
"WIDE_LENS": {
"name": "Lupa"
@ -294,20 +298,24 @@
"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": "Agrega un 30% de posibilidades de que una baya usada no se consuma."
"name": "Saco bayas",
"description": "Añade un 30% de posibilidades de que una baya no se gaste al usarla."
},
"FOCUS_BAND": {
"name": "Cinta Focus",
"name": "Banda aguante",
"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": {
@ -315,7 +323,7 @@
"description": "Cura 1/16 de los PS máximo de un Pokémon cada turno."
},
"SHELL_BELL": {
"name": "Camp Concha",
"name": "Cascabel concha",
"description": "Cura 1/8 del daño infligido por un Pokémon."
},
"TOXIC_ORB": {
@ -327,15 +335,15 @@
"description": "Extraña esfera que causa quemaduras a quien la usa en combate."
},
"BATON": {
"name": "Relevo",
"name": "Testigo",
"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": {
@ -346,60 +354,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 Daño",
"name": "Ficha de daño",
"description": "Aumenta el daño en un 5%."
},
"ENEMY_DAMAGE_REDUCTION": {
"name": "Ficha Protección",
"name": "Ficha de protección",
"description": "Reduce el daño recibido en un 2,5%."
},
"ENEMY_HEAL": {
"name": "Ficha Curación",
"name": "Ficha de 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."
}
},
@ -413,35 +421,35 @@
"dire_hit": "Crítico X"
},
"TempBattleStatBoosterStatName": {
"ATK": "Attack",
"DEF": "Defense",
"SPATK": "Sp. Atk",
"SPDEF": "Sp. Def",
"SPD": "Speed",
"ACC": "Accuracy",
"CRIT": "Critical Hit Ratio",
"EVA": "Evasiveness",
"ATK": "Ataque",
"DEF": "Defensa",
"SPATK": "Ataq. Esp.",
"SPDEF": "Def. Esp.",
"SPD": "Velocidad",
"ACC": "Precisión",
"CRIT": "Tasa de crítico",
"EVA": "Evasión",
"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": "Rev. Metálico",
"metal_coat": "Revest. 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 Hada"
"dragon_fang": "Colmillo dragón",
"black_glasses": "Gafas de sol",
"fairy_feather": "Pluma feérica"
},
"BaseStatBoosterItem": {
"hp_up": "Más PS",
@ -452,38 +460,38 @@
"carbos": "Carburante"
},
"EvolutionItem": {
"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"
"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"
},
"FormChangeItem": {
"NONE": "None",
"NONE": "Ninguno",
"ABOMASITE": "Abomasnowita",
"ABSOLITE": "Absolita",
"AERODACTYLITE": "Aerodactylita",
@ -532,70 +540,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": "Piedra Oscura",
"LIGHT_STONE": "Piedra Luminosa",
"PRISON_BOTTLE": "Vasija Castigo",
"MAX_MUSHROOMS": "Maxisetas",
"DARK_STONE": "Orbe oscuro",
"LIGHT_STONE": "Orbe claro",
"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 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 en 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 n'affecte pas {{pokemonNameWithAffix}}…",
"moveImmunity": "Ça naffecte 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": "The Pokémon gathers Honey after a battle. The Honey is then sold for money."
"description": "Le Pokémon trouve du Miel après un combat et est directement revendu contre de largent."
},
"frisk": {
"name": "Fouille",
"description": "Lorsqu'il entre en combat, le Pokémon peut vérifier la capacité d'un Pokémon adverse."
"description": "Lorsquil entre en combat, le Pokémon peut vérifier la capacité dun 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é, un talent ou un objet tenu."
"description": "Soigner {{healAmount}} {{HP}} en une fois avec une capacité,\nun 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é, un talent ou un objet tenu."
"description": "Soigner {{healAmount}} {{HP}} en une fois avec une capacité,\nun 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": "Génération {{generation}}"
}
"generation": "{{generation}}"
}

View File

@ -1,5 +1,5 @@
{
"music": "Musique : ",
"music": " : ",
"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 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",
"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",
"jungle": "Lmz - Jungle",
"laboratory": "Firel - Laboratory",
"lake": "PDM EdS - Caverne Cristal",
"meadow": "PDM EdS - Pic Céleste (forêt)",
"lake": "PDM EdC - Caverne Cristal",
"meadow": "PDM EdC - Pic Céleste (forêt)",
"metropolis": "Firel - Metropolis",
"mountain": "PDM EdS - Mt Corne",
"plains": "PDM EdS - Pic Céleste (prairie)",
"power_plant": "PDM EdS - Plaines Élek",
"ruins": "PDM EdS - Ruine Scellée",
"mountain": "PDM EdC - Mont Corne",
"plains": "PDM EdC - Pic Céleste (prairie)",
"power_plant": "PDM EdC - Plaines Élek",
"ruins": "PDM EdC - Ruine Scellée",
"sea": "Andr06 - Marine Mystique",
"seabed": "Firel - Seabed",
"slum": "Andr06 - Sneaky Snom",
"snowy_forest": "PDM EdS - Pic Céleste (plaine enneigée)",
"snowy_forest": "PDM EdC - Pic Céleste (plaine enneigée)",
"space": "Firel - Aether",
"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",
"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",
"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 EdS - Bienvenue dans le monde de Pokémon !",
"title": "PDM EdS - Menu Principal"
}
"menu": "PDM EdC - Bienvenue dans le monde de Pokémon !",
"title": "PDM EdC - Menu Principal"
}

View File

@ -1,7 +1,7 @@
{
"blue_red_double": {
"encounter": {
"1": "Blue : Hé Red, montrons-leur de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !"
"1": "Blue : Hé Red, montrons-lui 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-leur de quel bois on se chauffe !\n$Red : …\n$Blue : Voilà la puissance du Bourg Palette !"
"1": "Blue : Hé Red, montrons-lui 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 être pris au sérieux. Tes prête à te battre ?",
"6": "Un combat doit toujours être pris au sérieux.\nTes 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": "Peut importe à quel point taimes tes Pokémon, il faut toujours de la discipline sils se comportent mal."
"3": "Peu 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 c'est moi le génie des combats !",
"2": "Quoi ?! Mais cest moi le génie des combats !",
"3": "Évidemment que tes le personnage principal !",
"4": "OK ! OK ! Tu pourrais être une Topdresseuse !"
},
@ -169,50 +169,98 @@
},
"rocket_grunt": {
"encounter": {
"1": "Nous sommes de retour !"
"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 !"
},
"victory": {
"1": "Une fois de plus la Team Rocket senvole vers dautres cieux !"
"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 !"
}
},
"magma_grunt": {
"encounter": {
"1": "Nespère pas recevoir de la pitié si tu te mets sur le chemin de la Team Magma !"
"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é !"
},
"victory": {
"1": "Je…?\nJai perdu ?!"
"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 ?"
}
},
"aqua_grunt": {
"encounter": {
"1": "Aucune pitié si tu te mets sur le chemin de la Team Aqua, même pour une gamine !"
"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 !"
},
"victory": {
"1": "Comment ça ?"
"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 ?…"
}
},
"galactic_grunt": {
"encounter": {
"1": "Ne te mets pas en travers de la Team Galaxie !"
"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 !"
},
"victory": {
"1": "Désactivation…"
"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…"
}
},
"plasma_grunt": {
"encounter": {
"1": "Pas de quatiers à ceux qui ne suivent pas notre idéal !"
"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."
},
"victory": {
"1": "Plasmaaaaaaaaa !"
"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": "Le style et le bon gout, il ny a que ça qui compte !"
"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 !"
},
"victory": {
"1": "Mon futur me semble guère radieux."
"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 !"
}
},
"rocket_boss_giovanni_1": {
@ -223,7 +271,7 @@
"1": "QUOI ? IMPOSSIBLE !"
},
"defeat": {
"1": "Retiens bien. Ton incapacité à évaluer ta propre force est\nla démonstration claire que tu n'es encore quune gamine."
"1": "Retiens bien. Ton incapacité à évaluer ta propre force est\nla démonstration claire que tu nes encore quune gamine."
}
},
"rocket_boss_giovanni_2": {
@ -336,6 +384,77 @@
"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."
@ -349,7 +468,7 @@
},
"rival": {
"encounter": {
"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 !"
"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 !"
},
"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 !"
@ -441,7 +560,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 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."
"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."
},
"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."
@ -455,4 +574,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 être pris au sérieux. Tes prêt à te battre ?",
"6": "Un combat doit toujours être pris au sérieux.\nTes 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": "Peut importe à quel point taimes tes Pokémon, il faut toujours de la discipline sils se comportent mal."
"3": "Peu 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 t'arrives à ferrer une victoire !"
"3": "Voyons si tarrives à 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 c'est moi le génie des combats !",
"2": "Quoi ?! Mais cest moi le génie des combats !",
"3": "Évidemment que tes le personnage principal !",
"4": "OK ! OK ! Tu pourrais être un Topdresseur !"
},
@ -170,81 +170,97 @@
"rocket_grunt": {
"encounter": {
"1": "Nous sommes de retour !",
"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!"
"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 !"
},
"victory": {
"1": "Une fois de plus la Team Rocket senvole vers dautres cieux !",
"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?"
"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 !"
}
},
"magma_grunt": {
"encounter": {
"1": "Nespère pas recevoir de la pitié si tu te mets sur le chemin de la Team Magma !",
"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!"
"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é !"
},
"victory": {
"1": "Je…?\nJai perdu ?!",
"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?"
"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 ?"
}
},
"aqua_grunt": {
"encounter": {
"1": "Aucune pitié si tu te mets sur le chemin de la Team Aqua, même pour un gamin !",
"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!"
"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 !"
},
"victory": {
"1": "Comment ça ?",
"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?"
"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 ?…"
}
},
"galactic_grunt": {
"encounter": {
"1": "Ne te mets pas en travers de la Team Galaxie !",
"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!"
"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 !"
},
"victory": {
"1": "Désactivation…",
"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."
"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…"
}
},
"plasma_grunt": {
"encounter": {
"1": "Pas de quatiers à ceux qui ne suivent pas notre idéal !",
"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."
"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."
},
"victory": {
"1": "Plasmaaaaaaaaa !",
"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!"
"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 !"
}
},
"rocket_boss_giovanni_1": {
@ -379,6 +395,77 @@
"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 !"
@ -411,7 +498,7 @@
},
"rival_female": {
"encounter": {
"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 ?"
"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 ?"
},
"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 !"
@ -509,4 +596,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 sûrement mettre du temps à éclore.",
"hatchWavesMessageLongTime": "Cet Œuf va surement 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 Pokémon",
"renamePokemon": "Renommer le 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}} possède trop\ndexemplaires de cet objet !"
"tooMany": "{{pokemonName}} porte 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 le movepool)."
"description": "Fusionne deux Pokémon (transfère le talent, sépare les stats de base et les types, partage les capacités)."
},
"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": "50% des dégâts infligés sont convertis en argent." },
"GOLDEN_PUNCH": { "name": "Poing Doré", "description": "La moitié 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." },
"CANDY_JAR": { "name": "Bonbonnière", "description": "Augmente de 1 le nombre de niveaux gagnés à lutilisation dun Super Bonbon ou dun Hyper 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": "Attaque",
"DEF": "Défense",
"SPATK": "Atq. Spé.",
"SPDEF": "Déf. Spé.",
"SPD": "Vitesse",
"ACC": "Précision",
"CRIT": "Taux de critique",
"EVA": "Esquive",
"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",
"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": "{{pokemonNameWithAffix}}'s lowered stats were restored\nby its {{typeName}}!",
"pokemonResetNegativeStatStageApply": "Les stats baissées de {{pokemonNameWithAffix}}\nsont restaurées par l{{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 brûler (10% de chances)."
"effect": "Un coup de poing enflammé vient frapper la cible, ce qui peut la bruler (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 brûler."
"effect": "La cible est attaquée par une faible flamme qui peut aussi la bruler."
},
"flamethrower": {
"name": "Lance-Flammes",
"effect": "La cible reçoit un torrent de flammes qui peut aussi la brûler (10% de chances)."
"effect": "La cible reçoit un torrent de flammes qui peut aussi la bruler (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": "Abîme",
"name": "Abime",
"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 à l'aide d'une éruption de gaz répugnants qui peuvent aussi empoisonner la cible."
"effect": "Le lanceur attaque à laide dune é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 brûler (10% de chances)."
"effect": "Un déluge de flammes ardentes submerge la cible, ce qui peut aussi la bruler (10% de chances)."
},
"waterfall": {
"name": "Cascade",
@ -581,7 +581,7 @@
},
"dizzyPunch": {
"name": "Uppercut",
"effect": "Un enchaînement de coups de poing cadencés frappe lennemi. Peut aussi le rendre confus."
"effect": "Un enchainement 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": "Affûtage",
"name": "Affutage",
"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, brûler ou geler la cible (6.67% de chances)."
"effect": "Le lanceur envoie trois boules dénergie simultanément qui peuvent aussi paralyser, bruler 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 disparaît après utilisation."
"effect": "Le lanceur apprend la dernière capacité utilisée par la cible. Gribouille disparait 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 brûler (10% de chances)."
"effect": "Le lanceur sentoure de feu et charge la cible, ce qui peut aussi la bruler (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 brûler (50% de chances)."
"effect": "Le lanceur génère un feu mystique dune intensité redoutable pour attaquer lennemi. Peut aussi le bruler (50% de chances)."
},
"magnitude": {
"name": "Ampleur",
@ -1025,7 +1025,7 @@
},
"heatWave": {
"name": "Canicule",
"effect": "Le lanceur provoque une vague de chaleur qui peut aussi brûler la cible (10% de chances)."
"effect": "Le lanceur provoque une vague de chaleur qui peut aussi bruler 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 brûlure."
"effect": "Le lanceur projette des flammes maléfiques à la cible pour lui infliger une brulure."
},
"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 brûlé."
"effect": "Une capacité dont la puissance double lorsque le lanceur est empoisonné, paralysé ou brulé."
},
"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 brûlure ou dune paralysie."
"effect": "Le lanceur se repose pour guérir dun empoisonnement, dune brulure 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 Brûleur",
"effect": "Le lanceur envoie un coup de pied au taux de critiques élevé. Peut aussi brûler la cible (10% de chances)."
"name": "Pied Bruleur",
"effect": "Le lanceur envoie un coup de pied au taux de critiques élevé. Peut aussi bruler 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 brûler (10% de chances). Le choc blesse aussi gravement le lanceur."
"effect": "Le lanceur sembrase avant de charger la cible, ce qui peut la bruler (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 brûler (10% de chances) ou apeurer (10% de chances) la cible."
"effect": "Le lanceur utilise une morsure enflammée qui peut aussi bruler (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 brûler (10% de chances)."
"effect": "Des flammes sabattent sur tous les Pokémon autour du lanceur, ce qui peut aussi les bruler (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": "Piqûre",
"name": "Piqure",
"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 disparaît au premier tour et frappe la cible au deuxième. Cette capacité fonctionne même si la cible se protège."
"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."
},
"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 brûler (30% de chances)."
"effect": "Le lanceur projette un jet deau bouillante sur la cible, ce qui peut aussi la bruler (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 brûlé et devient inutilisable."
"effect": "Des flammes calcinent la cible. Si elle tient un objet, une Baie par exemple, celui-ci est brulé 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 brûlent."
"effect": "La cible est entourée dun torrent de flammes ardentes qui la brulent."
},
"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 apparaît."
"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."
},
"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 apparaît."
"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."
},
"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 apparaît."
"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."
},
"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 brûler (30% de chances)."
"effect": "Des boules de feu sabattent sur tous les Pokémon autour du lanceur. Peut aussi les bruler (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 brûler (20% de chances)."
"effect": "De magnifiques et redoutables flammes bleues fondent sur lennemi. Peut aussi le bruler (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 brûler (30% de chances)."
"effect": "Au second tour, le lanceur projette un souffle de vent glacial dévastateur sur lennemi. Peut aussi le bruler (30% de chances)."
},
"snarl": {
"name": "Aboiement",
@ -2261,7 +2261,7 @@
},
"phantomForce": {
"name": "Hantise",
"effect": "Le lanceur disparaît au premier tour et frappe au second. Cette attaque passe outre les protections."
"effect": "Le lanceur disparait 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échaîne un vent magique qui cingle la cible."
"effect": "Le lanceur déchaine un vent magique qui cingle la cible."
},
"moonblast": {
"name": "Pouvoir Lunaire",
@ -2345,7 +2345,7 @@
},
"fairyLock": {
"name": "Verrou Enchanté",
"effect": "Des chaînes entourent la zone de combat, empêchant tous les Pokémon de quitter le terrain au tour suivant."
"effect": "Des chaines 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 brûler (30% de chances)."
"effect": "Le lanceur projette de la vapeur extrêmement chaude sur la cible, ce qui peut aussi la bruler (30% de chances)."
},
"hyperspaceHole": {
"name": "TrouDimensionnel",
@ -2377,7 +2377,7 @@
},
"mysticalFire": {
"name": "Feu Ensorcelé",
"effect": "Le lanceur attaque en soufflant des flammes brûlantes par la bouche et diminue lAttaque Spéciale de la cible."
"effect": "Le lanceur attaque en soufflant des flammes brulantes 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 entraîner 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 entrainer 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 brûlures des Pokémon touchés par ces bulles."
"effect": "Le lanceur émet plusieurs bulles en chantant. Soigne les brulures 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 brûlé."
"effect": "Le lanceur fait chauffer son bec avant dattaquer. Sil subit une attaque directe pendant la montée en température, lattaquant sera brulé."
},
"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échaîne 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échaine 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échaîne toute la colère de la nature pour baisser les PV de la cible de moitié."
"effect": "Le lanceur déchaine 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échaîner sur la cible. Taux de critique élevé."
"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é."
},
"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échaînant toute sa puissance. Ignore le talent de la cible."
"effect": "Baigné dans la Force Z, Solgaleo attaque en déchainant 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échaînant toute sa puissance. Ignore le talent de la cible."
"effect": "Baigné dans la Force Z, Lunala attaque en déchainant 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 augmente lesquive. Frappe en priorité."
"effect": "Une attaque électrique rapide comme léclair qui inflige un coup critique à coup sûr. Frappe en priorité."
},
"splishySplash": {
"name": "Pika-Splash",
@ -2937,7 +2937,7 @@
},
"sizzlySlide": {
"name": "Évo-Flambo",
"effect": "Évoli sembrase et percure violemment ladversaire. Brûle aussi lennemi."
"effect": "Évoli sembrase et percure violemment ladversaire. Brule 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 apparaît 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 apparait 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 goûter 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 gouter 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 du lanceur."
"effect": "Augmente fortement lAttaque et lAttaque Spéciale de la cible."
},
"drumBeating": {
"name": "Tambour Battant",
@ -3116,8 +3116,8 @@
"effect": "Bloque lennemi pendant 4 à 5 tours."
},
"pyroBall": {
"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)."
"name": "Ballon Brulant",
"effect": "Le lanceur attaque avec un ballon fait à partir dun caillou enflammé. Peut aussi bruler 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 disparaître le champ actif, mais qui échoue sil ny en a pas à ce moment."
"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."
},
"scaleShot": {
"name": "Rafale Écailles",
@ -3225,7 +3225,7 @@
},
"burningJealousy": {
"name": "Feu Envieux",
"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."
"effect": "Le lanceur attaque sa cible avec toute sa jalousie. Cette capacité brule 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 brûler (30% de chances)."
"effect": "Le lanceur projette du sable chauffé à blanc sur la cible, ce qui peut aussi la bruler (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 maîtrisent 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 maitrisent 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 maîtrisent 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 maitrisent 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 brûlante, 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 brulante, 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échaîne et attaque en projetant de violentes flammes pendant deux ou trois tours. Il devient ensuite confus."
"effect": "Le lanceur se déchaine 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 brûler (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 bruler (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 brûler (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 bruler (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 enchaînement de coups permet dignorer la capacité Gardomax."
"effect": "Une attaque de type Eau que seul un Shifours Gigamax peut utiliser. Cet enchainement 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 Brûlant",
"effect": "Crash Brûlant inflige des dégâts et possède 30 % de chances de brûler ladversaire."
"name": "Crash Brulant",
"effect": "Crash Brulant inflige des dégâts et possède 30 % de chances de bruler 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 brûler 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 bruler 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 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."
"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."
},
"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 Envoûtante",
"name": "Voix Envoutante",
"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": "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."
"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."
}
}
}

View File

@ -11,7 +11,7 @@
"baker": "Boulangère",
"battle_girl": "Combattante",
"beauty": "Canon",
"beginners": "Beginners",
"beginners": "Débutants",
"biker": "Motard",
"black_belt": "Karatéka",
"breeder": "Éleveur",
@ -29,7 +29,7 @@
"depot_agent": "Cheminot",
"doctor": "Docteur",
"doctor_female": "Docteure",
"firebreather": "Firebreather",
"firebreather": "Crache-Feu",
"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": "Rich",
"rich": "Gentleman",
"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 aumenta l'elusione dell'utilizzatore."
"effect": "Un attacco elettrico ad altissima velocità. Questa mossa ha priorità alta e infligge sicuramente un brutto colpo."
},
"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 +1,42 @@
{}
{
"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": "Its disguise served it as a decoy!"
"disguiseChange": "Il costume ha assorbito lattacco!"
}

View File

@ -1,6 +1,6 @@
{
"confirmStartTeam": "Vuoi iniziare con questi Pokémon?",
"confirmExit": "Do you want to exit?",
"confirmExit": "Vuoi tornare alla schermata principale?",
"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": "Add to Favorites",
"removeFromFavorites": "Remove from Favorites",
"addToFavorites": "Aggiungi ai preferiti",
"removeFromFavorites": "Rimuovi dai preferiti",
"useCandies": "Usa caramelle",
"selectNature": "Seleziona natura.",
"selectMoveSwapOut": "Seleziona una mossa da scambiare.",
"selectMoveSwapWith": "Seleziona una mossa da scambiare con",
"sameSpeciesEgg": "Buy an Egg",
"sameSpeciesEgg": "Compra un uovo",
"unlockPassive": "Sblocca passiva",
"reduceCost": "Riduci costo",
"cycleShiny": ": Shiny",
@ -36,7 +36,7 @@
"cycleAbility": ": Abilità",
"cycleNature": ": Natura",
"cycleVariant": ": Variante",
"goFilter": ": Go to filters",
"goFilter": ": Vai ai filtri",
"enablePassive": "Attiva passiva",
"disablePassive": "Disattiva passiva",
"locked": "Bloccato",

View File

@ -1 +1,16 @@
{}
{
"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": "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",
"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",
"cyrus": "Cyrus",
"ghetsis": "Ghetsis",
"lysandre": "Lysandre",
"ghetsis": "Ghecis",
"lysandre": "Elisio",
"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": "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"
"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"
}

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 aumenta a Evasão do usuário."
"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."
},
"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": "迅猛无比的电击。必定能够先制攻击,\n并且提高自己的闪避率。"
"effect": "迅猛无比的电击。必定能够先制攻击,击中对方的要害。"
},
"splishySplash": {
"name": "滔滔冲浪",
@ -3807,4 +3807,4 @@
"name": "邪毒锁链",
"effect": "用由毒形成的锁链缠住对手注入毒\n素加以侵蚀。有时会让对手陷入剧毒状态"
}
}
}

View File

@ -311,8 +311,6 @@ 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,19 +1,18 @@
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 { allAbilities } from "#app/data/ability";
import { Abilities } from "#app/enums/abilities";
import { WeatherType } from "#app/enums/weather-type";
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 { VictoryPhase } from "#app/phases/victory-phase";
import { allAbilities } from "#app/data/ability";
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("Abilities - Forecast", () => {
let phaserGame: Phaser.Game;
@ -31,7 +30,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);
@ -53,54 +52,6 @@ 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,
@ -113,55 +64,127 @@ describe("Abilities - Forecast", () => {
beforeEach(() => {
game = new GameManager(phaserGame);
game.override.moveset([ Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.TACKLE ])
game.override
.moveset([Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.TACKLE])
.enemySpecies(Species.MAGIKARP)
.enemyMoveset(SPLASH_ONLY)
.enemyAbility(Abilities.BALL_FETCH);
});
it("changes to Sunny Form during Harsh Sunlight", async () => {
await testWeatherFormChange(game, WeatherType.SUNNY, SUNNY_FORM);
});
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 Extreme Harsh Sunlight", async () => {
await testWeatherFormChange(game, WeatherType.HARSH_SUN, SUNNY_FORM);
});
vi.spyOn(game.scene.getParty()[5], "getAbility").mockReturnValue(allAbilities[Abilities.CLOUD_NINE]);
it("changes to Rainy Form during Rain", async () => {
await testWeatherFormChange(game, WeatherType.RAIN, RAINY_FORM);
});
const castform = game.scene.getPlayerField()[0];
expect(castform.formIndex).toBe(NORMAL_FORM);
it("changes to Rainy Form during Heavy Rain", async () => {
await testWeatherFormChange(game, WeatherType.HEAVY_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 Snowy Form during Hail", async () => {
await testWeatherFormChange(game, WeatherType.HAIL, SNOWY_FORM);
});
expect(castform.formIndex).toBe(RAINY_FORM);
it("changes to Snowy Form during Snow", async () => {
await testWeatherFormChange(game, WeatherType.SNOW, SNOWY_FORM);
});
game.move.select(Moves.SUNNY_DAY);
game.move.select(Moves.SPLASH, 1);
await game.phaseInterceptor.to("MovePhase");
await game.toNextTurn();
it("reverts to Normal Form during Sandstorm", async () => {
await testWeatherFormChange(game, WeatherType.SANDSTORM, NORMAL_FORM, SUNNY_FORM);
});
expect(castform.formIndex).toBe(SUNNY_FORM);
it("reverts to Normal Form during Fog", async () => {
await testWeatherFormChange(game, WeatherType.FOG, 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 Strong Winds", async () => {
await testWeatherFormChange(game, WeatherType.STRONG_WINDS, 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 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);
});
@ -177,93 +200,50 @@ describe("Abilities - Forecast", () => {
expect(game.scene.getEnemyPokemon()?.formIndex).not.toBe(RAINY_FORM);
});
it("cannot be copied", async () => {
game.override.enemyAbility(Abilities.TRACE);
await game.startBattle([Species.CASTFORM]);
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]);
game.move.select(Moves.SPLASH);
const castform = game.scene.getPlayerField()[0];
expect(game.scene.getEnemyPokemon()?.hasAbility(Abilities.FORECAST)).toBe(false);
});
expect(castform.formIndex).toBe(RAINY_FORM);
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();
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]);
expect(castform?.formIndex).toBe(RAINY_FORM);
await game.phaseInterceptor.to("MoveEndPhase");
expect(castform.formIndex).toBe(NORMAL_FORM);
// First turn - loses Forecast
game.move.select(Moves.SKILL_SWAP);
await game.phaseInterceptor.to(TurnEndPhase);
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.phaseInterceptor.to("MoveEndPhase");
expect(castform.formIndex).toBe(RAINY_FORM);
await game.toNextTurn();
// Second turn - switch out Castform, regains Forecast
game.doSwitchPokemon(1);
await game.toNextTurn();
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");
// Third turn - switch in Castform
game.doSwitchPokemon(1);
await game.phaseInterceptor.to(MovePhase);
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);
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();
const castform = game.scene.getPlayerPokemon()!;
expect(castform?.formIndex).toBe(RAINY_FORM);
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.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);
expect(castform.summonData.abilitySuppressed).toBe(true);
expect(castform.formIndex).toBe(NORMAL_FORM);
await game.toNextTurn();
@ -275,21 +255,8 @@ describe("Abilities - Forecast", () => {
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);
expect(castform.summonData.abilitySuppressed).toBe(false);
expect(castform.formIndex).toBe(RAINY_FORM);
});
it("does not change Castform's form until after Stealth Rock deals damage", async () => {
@ -304,31 +271,15 @@ 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() ?? 0);
expect(castform.hp).toBeLessThan(castform.getMaxHp());
// Then change form
await game.phaseInterceptor.to(QuietFormChangePhase);
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);
expect(castform.formIndex).toBe(RAINY_FORM);
});
it("should be in Normal Form after the user is switched out", async () => {

View File

@ -0,0 +1,133 @@
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].defaultType];
const moveType = Type[allMoves[Moves.AGILITY].type];
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].defaultType];
leadPokemon.summonData.types = [allMoves[Moves.SPLASH].type];
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].defaultType];
moveType = Type[allMoves[move].type];
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].defaultType];
const moveType = Type[allMoves[Moves.AGILITY].type];
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].defaultType];
leadPokemon.summonData.types = [allMoves[Moves.SPLASH].type];
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].defaultType];
moveType = Type[allMoves[move].type];
expect(pokemonType).toBe(moveType);
}

View File

@ -0,0 +1,70 @@
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

@ -0,0 +1,83 @@
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 { getMoveTargets } from "#app/data/move";
import { BattlerIndex } from "#app/battle";
import { Abilities } from "#app/enums/abilities";
import { Species } from "#app/enums/species";
import { TurnEndPhase } from "#app/phases/turn-end-phase";
import * as Utils from "#app/utils";
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("Moves - Multi target", () => {
describe("Multi-target damage reduction", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
@ -21,160 +21,111 @@ describe("Moves - Multi target", () => {
});
afterEach(() => {
afterTrial(game);
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = beforeTrial(phaserGame);
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);
});
it("2v2 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, false, false, true), TIMEOUT);
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 - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, false, false, true), TIMEOUT);
const [enemy1, enemy2] = game.scene.getEnemyField();
it("2v1 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, false, true, 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 - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, false, true, true), TIMEOUT);
const gleam1 = enemy1.getMaxHp() - enemy1.hp;
enemy1.hp = enemy1.getMaxHp();
it("1v2 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, true, false, true), TIMEOUT);
await game.phaseInterceptor.to("MoveEndPhase");
it("1v2 - target all near others - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, true, false, true), TIMEOUT);
const tackle1 = enemy1.getMaxHp() - enemy1.hp;
enemy1.hp = enemy1.getMaxHp();
it("1v1 - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, true, true, false), TIMEOUT);
await game.killPokemon(enemy2);
await game.toNextTurn();
it("2v2 (immune) - target all near others - check modifier", () => checkTargetMultiplier(game, Moves.EARTHQUAKE, false, false, true, Abilities.LEVITATE), 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 - damage decrase", () => checkDamageDecrease(game, Moves.EARTHQUAKE, false, false, true, Abilities.LEVITATE), TIMEOUT);
await game.phaseInterceptor.to("MoveEndPhase");
it("2v2 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, false, false, true), TIMEOUT);
const gleam2 = enemy1.getMaxHp() - enemy1.hp;
enemy1.hp = enemy1.getMaxHp();
it("2v2 - target all near enemies - damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, false, false, true), TIMEOUT);
await game.phaseInterceptor.to("MoveEndPhase");
const tackle2 = enemy1.getMaxHp() - enemy1.hp;
it("2v1 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, false, true, false), 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 - no damage decrase", () => checkDamageDecrease(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("1v2 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, true, false, true), TIMEOUT);
const player2 = game.scene.getParty()[1];
const [enemy1, enemy2] = game.scene.getEnemyField();
it("1v2 - target all near enemies - damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, true, false, true), TIMEOUT);
it("1v1 - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, true, true, false), TIMEOUT);
it("2v2 (immune) - target all near enemies - check modifier", () => checkTargetMultiplier(game, Moves.HYPER_VOICE, false, false, true, Abilities.SOUNDPROOF), TIMEOUT);
it("2v2 (immune) - target all near enemies - damage decrase", () => checkDamageDecrease(game, Moves.HYPER_VOICE, false, false, true, Abilities.SOUNDPROOF), 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.EARTHQUAKE);
game.move.select(Moves.SPLASH, 1);
}
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to(TurnEndPhase);
const afterHp = game.scene.getEnemyField()[0].hp;
await game.phaseInterceptor.to("MoveEndPhase");
killAllyAndEnemy(game, true, true);
await game.toNextTurn();
const damagePlayer2Turn1 = player2.getMaxHp() - player2.hp;
const damageEnemy1Turn1 = enemy1.getMaxHp() - enemy1.hp;
game.scene.getEnemyField()[0].hp = initialHp;
player2.hp = player2.getMaxHp();
enemy1.hp = enemy1.getMaxHp();
const initialHp1v1 = game.scene.getEnemyField()[0].hp;
game.move.select(attackMove);
await game.killPokemon(enemy2);
await game.toNextTurn();
await game.phaseInterceptor.to(TurnEndPhase);
const afterHp1v1 = game.scene.getEnemyField()[0].hp;
game.move.select(Moves.EARTHQUAKE);
game.move.select(Moves.SPLASH, 1);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]);
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);
}
await game.phaseInterceptor.to("MoveEndPhase");
}
const damagePlayer2Turn2 = player2.getMaxHp() - player2.hp;
const damageEnemy1Turn2 = enemy1.getMaxHp() - enemy1.hp;
// 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);
}
}
enemy1.hp = enemy1.getMaxHp();
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);
}
// Turn 1: 3 targets, turn 2: 2 targets
// Both should have damage reduction
expect(damageEnemy1Turn1).toBe(damageEnemy1Turn2);
expect(damagePlayer2Turn1).toBe(damagePlayer2Turn2);
function leaveOneEnemyPokemon(game: GameManager) {
const enemyPokemons = game.scene.getEnemyParty();
for (let i = 1; i < enemyPokemons.length; i++) {
enemyPokemons[i].hp = 0;
}
}
await game.killPokemon(player2);
await game.toNextTurn();
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;
}
game.move.select(Moves.EARTHQUAKE);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
function afterTrial(game: GameManager) {
game.phaseInterceptor.restoreOg();
}
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);
});

View File

@ -62,9 +62,6 @@ 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();
@ -72,9 +69,25 @@ describe("Moves - Tera Blast", () => {
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]);
await game.phaseInterceptor.to("MoveEffectPhase");
expect(moveToCheck.calculateBattlePower).toHaveReturnedWith((basePower + stellarTypeDmgBonus) * stellarTypeMultiplier);
expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(100);
}, 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

@ -0,0 +1,102 @@
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 = 160;
this.defaultWidth = 200;
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,6 +15,16 @@ 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;
@ -105,8 +115,13 @@ 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);
this.titleText.setPositionRelative(titleBg, 8, 4);
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);
const scoreBg = addWindow(this.scene, titleBg.x + titleBg.width, titleBg.y, 46, 24);
scoreBg.setOrigin(0, 0);

View File

@ -35,6 +35,8 @@ export default class GameChallengesUiHandler extends UiHandler {
private startCursor: Phaser.GameObjects.NineSlice;
private optionsWidth: number;
constructor(scene: BattleScene, mode: Mode | null = null) {
super(scene, mode);
}
@ -74,18 +76,19 @@ export default class GameChallengesUiHandler extends UiHandler {
// difficultyName.setOrigin(0, 0);
// difficultyName.setPositionRelative(difficultyBg, difficultyBg.width - difficultyName.displayWidth - 8, 4);
this.optionsBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 9), (this.scene.game.canvas.height / 6) - headerBg.height - 2);
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.setName("window-options-bg");
this.optionsBg.setOrigin(0, 0);
const descriptionBg = addWindow(this.scene, 0, headerBg.height, (this.scene.game.canvas.width / 18) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 26);
const descriptionBg = addWindow(this.scene, 0, headerBg.height, this.scene.scaledCanvas.width - this.optionsWidth, this.scene.scaledCanvas.height - 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: 96,
fontSize: 84,
color: Color.ORANGE,
padding: {
bottom: 6
@ -109,12 +112,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, 8, 4);
startText.setPositionRelative(startBg, (startBg.width - startText.displayWidth) / 2, 4);
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 = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, descriptionBg.width - 8, 16, 1, 1, 1, 1);
this.startCursor.setName("9s-start-cursor");
this.startCursor.setOrigin(0, 0);
this.startCursor.setPositionRelative(startBg, 4, 4);
this.startCursor.setPositionRelative(startBg, 4, 3);
this.startCursor.setVisible(false);
this.valuesContainer = this.scene.add.container(0, 0);
@ -140,7 +143,7 @@ export default class GameChallengesUiHandler extends UiHandler {
};
}
this.monoTypeValue = this.scene.add.sprite(8, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
this.monoTypeValue = this.scene.add.sprite(8, 98, Utils.getLocalizedSpriteKey("types"));
this.monoTypeValue.setName("challenge-value-monotype-sprite");
this.monoTypeValue.setScale(0.86);
this.monoTypeValue.setVisible(false);
@ -355,7 +358,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.scene.game.canvas.width / 9) - 10, 16, 1, 1, 1, 1);
this.cursorObj = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, this.optionsWidth - 8, 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, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, "unknown");
this.typeIcon = this.scene.add.sprite(this.scene.scaledCanvas.width - 57, -36, Utils.getLocalizedSpriteKey("types"), "unknown");
this.typeIcon.setVisible(false);
this.moveInfoContainer.add(this.typeIcon);
@ -179,15 +179,20 @@ export default class FightUiHandler extends UiHandler {
if (hasMove) {
const pokemonMove = moveset[cursor]!; // TODO: is the bang correct?
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 moveType = pokemon.getMoveType(pokemonMove.getMove());
const textureKey = Utils.getLocalizedSpriteKey("types");
this.typeIcon.setTexture(textureKey, Type[moveType].toLowerCase()).setScale(0.8);
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;
this.ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`);
const ppLeftStr = Utils.padInt(pp, 2, " ");
const ppMaxStr = Utils.padInt(maxPP, 2, " ");
this.ppText.setText(`${ppLeftStr}/${ppMaxStr}`);
this.powerText.setText(`${power >= 0 ? power : "---"}`);
this.accuracyText.setText(`${accuracy >= 0 ? accuracy : "---"}`);
@ -231,7 +236,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);
const effectiveness = opponent.getMoveEffectiveness(pokemon, pokemonMove.getMove(), !opponent.battleData?.abilityRevealed);
if (effectiveness === undefined) {
return undefined;
}
@ -274,7 +279,7 @@ export default class FightUiHandler extends UiHandler {
}
const moveColors = opponents
.map((opponent) => opponent.getMoveEffectiveness(pokemon, pokemonMove))
.map((opponent) => opponent.getMoveEffectiveness(pokemon, pokemonMove.getMove(), !opponent.battleData.abilityRevealed))
.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, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
const typeSprite = this.scene.add.sprite(0, 0, Utils.getLocalizedSpriteKey("types"));
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, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
this.type1Icon = this.scene.add.sprite(8, 98, Utils.getLocalizedSpriteKey("types"));
this.type1Icon.setScale(0.5);
this.type1Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type1Icon);
this.type2Icon = this.scene.add.sprite(26, 98, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`);
this.type2Icon = this.scene.add.sprite(26, 98, Utils.getLocalizedSpriteKey("types"));
this.type2Icon.setScale(0.5);
this.type2Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type2Icon);

View File

@ -716,7 +716,8 @@ 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, `types${Utils.verifyLang(i18next.resolvedLanguage) ? `_${i18next.resolvedLanguage}` : ""}`, Type[type].toLowerCase()) : this.scene.add.sprite(xCoord, 42, "type_tera");
? this.scene.add.sprite(xCoord, 42, Utils.getLocalizedSpriteKey("types"), Type[type].toLowerCase())
: this.scene.add.sprite(xCoord, 42, "type_tera");
if (tera) {
typeIcon.setScale(0.5);
const typeRgb = getTypeRgb(type);
@ -934,10 +935,14 @@ 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);
@ -956,8 +961,11 @@ export default class SummaryUiHandler extends UiHandler {
const moveRowContainer = this.scene.add.container(0, 16 * m);
this.moveRowsContainer.add(moveRowContainer);
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);
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);
moveRowContainer.add(typeIcon);
}

View File

@ -574,3 +574,12 @@ 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}` : ""}`;
}