Merge branch 'pagefaultgames:main' into main
|
@ -15,19 +15,19 @@
|
|||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 37,
|
||||
"h": 35
|
||||
"h": 37
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 37,
|
||||
"h": 35
|
||||
"h": 37
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 37,
|
||||
"h": 35
|
||||
"h": 37
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -36,6 +36,6 @@
|
|||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:fa61a53a0684a1d00e0ed5d6737743af:3e6463caf33bbb58cfba4bd9c20890aa:37281ac0aa1e619ef385b889b64064b7$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 470 B |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.8 KiB |
|
@ -15,19 +15,19 @@
|
|||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 37,
|
||||
"h": 35
|
||||
"h": 37
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 37,
|
||||
"h": 35
|
||||
"h": 37
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 37,
|
||||
"h": 35
|
||||
"h": 37
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -36,6 +36,6 @@
|
|||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:29265d2eed2689ecb95874383b7e7da7:1339971def468ab6d7c93a72472c7b3d:37281ac0aa1e619ef385b889b64064b7$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 472 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 1.1 KiB |
|
@ -1227,6 +1227,7 @@ export default class BattleScene extends SceneBase {
|
|||
case Species.ZARUDE:
|
||||
case Species.SQUAWKABILLY:
|
||||
case Species.TATSUGIRI:
|
||||
case Species.GIMMIGHOUL:
|
||||
case Species.PALDEA_TAUROS:
|
||||
return Utils.randSeedInt(species.forms.length);
|
||||
case Species.PIKACHU:
|
||||
|
|
|
@ -1296,6 +1296,7 @@ export class AddSecondStrikeAbAttr extends PreAttackAbAttr {
|
|||
const multiplier = args[2] as Utils.NumberHolder;
|
||||
|
||||
if (this.canApplyPreAttack(move, numTargets)) {
|
||||
this.showAbility = !!hitCount?.value;
|
||||
if (!!hitCount?.value) {
|
||||
hitCount.value *= 2;
|
||||
}
|
||||
|
|
|
@ -935,9 +935,11 @@ export class ContactDamageProtectedTag extends ProtectedTag {
|
|||
const effectPhase = pokemon.scene.getCurrentPhase();
|
||||
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) {
|
||||
const attacker = effectPhase.getPokemon();
|
||||
if (!attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
|
||||
attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2961,9 +2961,29 @@ export class HpPowerAttr extends VariablePowerAttr {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for moves whose base power scales with the opponent's HP
|
||||
* Used for Crush Grip, Wring Out, and Hard Press
|
||||
* maxBasePower 100 for Hard Press, 120 for others
|
||||
*/
|
||||
export class OpponentHighHpPowerAttr extends VariablePowerAttr {
|
||||
maxBasePower: number;
|
||||
|
||||
constructor(maxBasePower: number) {
|
||||
super();
|
||||
this.maxBasePower = maxBasePower;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the base power of the move to be the target's HP ratio times the maxBasePower with a min value of 1
|
||||
* @param user n/a
|
||||
* @param target the Pokemon being attacked
|
||||
* @param move n/a
|
||||
* @param args holds the base power of the move at args[0]
|
||||
* @returns true
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.NumberHolder).value = Math.max(Math.floor(120 * target.getHpRatio()), 1);
|
||||
(args[0] as Utils.NumberHolder).value = Math.max(Math.floor(this.maxBasePower * target.getHpRatio()), 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -6705,7 +6725,7 @@ export function initMoves() {
|
|||
.target(MoveTarget.ALL_NEAR_ENEMIES)
|
||||
.unimplemented(),
|
||||
new AttackMove(Moves.WRING_OUT, Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 4)
|
||||
.attr(OpponentHighHpPowerAttr)
|
||||
.attr(OpponentHighHpPowerAttr, 120)
|
||||
.makesContact(),
|
||||
new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4)
|
||||
.unimplemented(),
|
||||
|
@ -6929,7 +6949,7 @@ export function initMoves() {
|
|||
.triageMove()
|
||||
.unimplemented(),
|
||||
new AttackMove(Moves.CRUSH_GRIP, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4)
|
||||
.attr(OpponentHighHpPowerAttr),
|
||||
.attr(OpponentHighHpPowerAttr, 120),
|
||||
new AttackMove(Moves.MAGMA_STORM, Type.FIRE, MoveCategory.SPECIAL, 100, 75, 5, -1, 0, 4)
|
||||
.attr(TrapAttr, BattlerTagType.MAGMA_STORM),
|
||||
new StatusMove(Moves.DARK_VOID, Type.DARK, 50, 10, -1, 0, 4)
|
||||
|
@ -8399,8 +8419,8 @@ export function initMoves() {
|
|||
new AttackMove(Moves.TACHYON_CUTTER, Type.STEEL, MoveCategory.SPECIAL, 50, -1, 10, -1, 0, 9)
|
||||
.attr(MultiHitAttr, MultiHitType._2)
|
||||
.slicingMove(),
|
||||
new AttackMove(Moves.HARD_PRESS, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9)
|
||||
.attr(OpponentHighHpPowerAttr),
|
||||
new AttackMove(Moves.HARD_PRESS, Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, -1, 0, 9)
|
||||
.attr(OpponentHighHpPowerAttr, 100),
|
||||
new StatusMove(Moves.DRAGON_CHEER, Type.DRAGON, -1, 15, -1, 0, 9)
|
||||
.attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, false, true)
|
||||
.target(MoveTarget.NEAR_ALLY)
|
||||
|
|
|
@ -1618,7 +1618,8 @@ export const pokemonEvolutions: PokemonEvolutions = {
|
|||
new SpeciesEvolution(Species.FROSMOTH, 1, null, new SpeciesFriendshipEvolutionCondition(90, p => p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), SpeciesWildEvolutionDelay.MEDIUM)
|
||||
],
|
||||
[Species.GIMMIGHOUL]: [
|
||||
new SpeciesEvolution(Species.GHOLDENGO, 1, null, new SpeciesFriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.VERY_LONG)
|
||||
new SpeciesFormEvolution(Species.GHOLDENGO, "chest", "", 1, null, new SpeciesFriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.VERY_LONG),
|
||||
new SpeciesFormEvolution(Species.GHOLDENGO, "roaming", "", 1, null, new SpeciesFriendshipEvolutionCondition(70), SpeciesWildEvolutionDelay.VERY_LONG)
|
||||
]
|
||||
};
|
||||
|
||||
|
|
|
@ -38685,6 +38685,8 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.GOLDEEN,
|
||||
Species.SEAKING,
|
||||
Species.SCYTHER,
|
||||
Species.ELECTABUZZ,
|
||||
Species.MAGMAR,
|
||||
Species.PINSIR,
|
||||
Species.OMANYTE,
|
||||
Species.OMASTAR,
|
||||
|
@ -38692,6 +38694,8 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.KABUTOPS,
|
||||
Species.MEWTWO,
|
||||
Species.MEW,
|
||||
Species.BAYLEEF,
|
||||
Species.MEGANIUM,
|
||||
Species.SENTRET,
|
||||
Species.FURRET,
|
||||
Species.LEDYBA,
|
||||
|
@ -38708,8 +38712,10 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.SNEASEL,
|
||||
Species.PHANPY,
|
||||
Species.DONPHAN,
|
||||
Species.ELEKID,
|
||||
Species.TYRANITAR,
|
||||
Species.BLAZIKEN,
|
||||
Species.SWAMPERT,
|
||||
Species.LOMBRE,
|
||||
Species.LUDICOLO,
|
||||
Species.NUZLEAF,
|
||||
|
@ -38740,12 +38746,7 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.CHIMECHO,
|
||||
Species.ABSOL,
|
||||
Species.METAGROSS,
|
||||
[
|
||||
Species.DEOXYS,
|
||||
"",
|
||||
"defense",
|
||||
"speed",
|
||||
],
|
||||
Species.CHIMCHAR,
|
||||
Species.MONFERNO,
|
||||
Species.INFERNAPE,
|
||||
|
@ -38767,6 +38768,8 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.WEAVILE,
|
||||
Species.LICKILICKY,
|
||||
Species.TANGROWTH,
|
||||
Species.ELECTIVIRE,
|
||||
Species.MAGMORTAR,
|
||||
Species.LEAFEON,
|
||||
Species.GLISCOR,
|
||||
Species.MAMOSWINE,
|
||||
|
@ -38781,6 +38784,8 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.SNIVY,
|
||||
Species.SERVINE,
|
||||
Species.SERPERIOR,
|
||||
Species.PIGNITE,
|
||||
Species.EMBOAR,
|
||||
Species.OSHAWOTT,
|
||||
Species.DEWOTT,
|
||||
Species.SAMUROTT,
|
||||
|
@ -38837,6 +38842,8 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.ACCELGOR,
|
||||
Species.MIENFOO,
|
||||
Species.MIENSHAO,
|
||||
Species.GOLETT,
|
||||
Species.GOLURK,
|
||||
Species.PAWNIARD,
|
||||
Species.BISHARP,
|
||||
Species.VULLABY,
|
||||
|
@ -38873,6 +38880,7 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.SALAZZLE,
|
||||
Species.STEENEE,
|
||||
Species.TSAREENA,
|
||||
Species.COMFEY,
|
||||
Species.ORANGURU,
|
||||
Species.PASSIMIAN,
|
||||
Species.GOLISOPOD,
|
||||
|
@ -38945,6 +38953,7 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.GALAR_FARFETCHD,
|
||||
Species.GALAR_ZAPDOS,
|
||||
Species.GALAR_ZIGZAGOON,
|
||||
Species.GALAR_LINOONE,
|
||||
Species.HISUI_SAMUROTT,
|
||||
Species.HISUI_ZORUA,
|
||||
Species.HISUI_ZOROARK,
|
||||
|
@ -61853,6 +61862,7 @@ export const tmSpecies: TmSpecies = {
|
|||
Species.METANG,
|
||||
Species.METAGROSS,
|
||||
Species.JIRACHI,
|
||||
Species.DEOXYS,
|
||||
Species.BRONZOR,
|
||||
Species.BRONZONG,
|
||||
Species.GALLADE,
|
||||
|
|
|
@ -1162,7 +1162,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return (!cancelled.value ? Number(typeMultiplier.value) : 0) as TypeDamageMultiplier;
|
||||
}
|
||||
|
||||
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false): TypeDamageMultiplier {
|
||||
/**
|
||||
* Calculates the type effectiveness multiplier for an attack type
|
||||
* @param moveType Type of the move
|
||||
* @param source the Pokemon using the move
|
||||
* @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks)
|
||||
* @param simulated tag to only apply the strong winds effect message when the move is used
|
||||
* @returns a multiplier for the type effectiveness
|
||||
*/
|
||||
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier {
|
||||
if (moveType === Type.STELLAR) {
|
||||
return this.isTerastallized() ? 2 : 1;
|
||||
}
|
||||
|
@ -1183,8 +1191,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier;
|
||||
|
||||
// Handle strong winds lowering effectiveness of types super effective against pure flying
|
||||
if (!ignoreStrongWinds && this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && multiplier >= 2 && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) {
|
||||
if (!ignoreStrongWinds && this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) {
|
||||
multiplier /= 2;
|
||||
if (!simulated) {
|
||||
this.scene.queueMessage(i18next.t("weather:strongWindsEffectMessage"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!!this.summonData?.tags.find((tag) => tag instanceof TypeImmuneTag && tag.immuneType === moveType)) {
|
||||
|
@ -1739,7 +1750,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
const cancelled = new Utils.BooleanHolder(false);
|
||||
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.type, source)
|
||||
? this.getAttackTypeEffectiveness(move.type, source, false, false)
|
||||
: 1);
|
||||
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
|
||||
if (typeless) {
|
||||
|
|
|
@ -78,6 +78,7 @@ export class LoadingScene extends SceneBase {
|
|||
this.loadImage("overlay_exp", "ui");
|
||||
this.loadImage("icon_owned", "ui");
|
||||
this.loadImage("ability_bar_left", "ui");
|
||||
this.loadImage("bgm_bar", "ui");
|
||||
this.loadImage("party_exp_bar", "ui");
|
||||
this.loadImage("achv_bar", "ui");
|
||||
this.loadImage("achv_bar_2", "ui");
|
||||
|
|
|
@ -25,6 +25,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "Es hat keine Wirkung auf {{pokemonName}}…",
|
||||
"hitResultOneHitKO": "Ein K.O.-Treffer!",
|
||||
"attackFailed": "Es ist fehlgeschlagen!",
|
||||
"attackMissed": "Die Attacke hat {{pokemonNameWithAffix}} verfehlt!",
|
||||
"attackHitsCount": "{{count}}-mal getroffen!",
|
||||
"rewardGain": "Du erhältst\n{{modifierName}}!",
|
||||
"expGain": "{{pokemonName}} erhält\n{{exp}} Erfahrungspunkte!",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Musik",
|
||||
"music": "Musik: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "S2W2 Vs. Kanto Champion",
|
||||
"battle_johto_champion": "S2W2 Vs. Johto Champion",
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "Alle Flug-Pokémon werden von rätselhaften Luftströmungen geschützt!",
|
||||
"strongWindsLapseMessage": "Die rätselhafte Luftströmung hält an.",
|
||||
"strongWindsEffectMessage": "Rätselhafte Luftströmungen haben den Angriff abgeschwächt!",
|
||||
"strongWindsClearMessage": "Die rätselhafte Luftströmung hat sich wieder geleget.",
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "It doesn't affect {{pokemonName}}!",
|
||||
"hitResultOneHitKO": "It's a one-hit KO!",
|
||||
"attackFailed": "But it failed!",
|
||||
"attackMissed": "{{pokemonNameWithAffix}} avoided the attack!",
|
||||
"attackHitsCount": "Hit {{count}} time(s)!",
|
||||
"rewardGain": "You received\n{{modifierName}}!",
|
||||
"expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Music",
|
||||
"music": "Music: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "B2W2 Kanto Champion Battle",
|
||||
"battle_johto_champion": "B2W2 Johto Champion Battle",
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "A heavy wind began!",
|
||||
"strongWindsLapseMessage": "The wind blows intensely.",
|
||||
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
|
||||
"strongWindsClearMessage": "The heavy wind stopped."
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "No afecta a {{pokemonName}}!",
|
||||
"hitResultOneHitKO": "¡KO en 1 golpe!",
|
||||
"attackFailed": "¡Pero ha fallado!",
|
||||
"attackMissed": "¡{{pokemonNameWithAffix}}\nha evitado el ataque!",
|
||||
"attackHitsCount": "N.º de golpes: {{count}}.",
|
||||
"rewardGain": "¡Has obtenido\n{{modifierName}}!",
|
||||
"expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Música",
|
||||
"music": "Música: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "B2W2 - ¡Vs Campeón de Kanto!",
|
||||
"battle_johto_champion": "B2W2 - ¡Vs Campeón de Johto!",
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "¡Comenzó un fuerte viento!",
|
||||
"strongWindsLapseMessage": "El viento sopla intensamente.",
|
||||
"strongWindsEffectMessage": "¡Las misteriosas turbulencias atenúan el ataque!",
|
||||
"strongWindsClearMessage": "El fuerte viento cesó."
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "Ça n’affecte pas {{pokemonName}}…",
|
||||
"hitResultOneHitKO": "K.O. en un coup !",
|
||||
"attackFailed": "Mais cela échoue !",
|
||||
"attackMissed": "{{pokemonNameWithAffix}}\névite l’attaque !",
|
||||
"attackHitsCount": "Touché {{count}} fois !",
|
||||
"rewardGain": "Vous recevez\n{{modifierName}} !",
|
||||
"expGain": "{{pokemonName}} gagne\n{{exp}} Points d’Exp !",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Musique ",
|
||||
"music": "Musique : ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "N2B2 - Vs. Maitre de Kanto",
|
||||
"battle_johto_champion": "N2B2 - Vs. Maitre de Johto",
|
||||
|
|
|
@ -28,7 +28,7 @@ export const partyUiHandler: SimpleTranslationEntries = {
|
|||
"unspliceConfirmation": "Voulez-vous vraiment séparer {{fusionName}}\nde {{pokemonName}} ? {{fusionName}} sera perdu.",
|
||||
"wasReverted": "{{fusionName}} est redevenu {{pokemonName}}.",
|
||||
"releaseConfirmation": "Voulez-vous relâcher {{pokemonName}} ?",
|
||||
"releaseInBattle": "Vous ne pouvez pas relâcher Pokémon en combat !",
|
||||
"releaseInBattle": "Vous ne pouvez pas relâcher un Pokémon en combat !",
|
||||
"selectAMove": "Sélectionnez une capacité.",
|
||||
"changeQuantity": "Sélect. un objet à transférer.\nChangez la quantité avec < et >.",
|
||||
"selectAnotherPokemonToSplice": "Sélectionnez un autre Pokémon à séparer.",
|
||||
|
@ -44,7 +44,7 @@ export const partyUiHandler: SimpleTranslationEntries = {
|
|||
"byebye": "Bye-bye, {{pokemonName}} !",
|
||||
"farewell": "Adieu, {{pokemonName}} !",
|
||||
"soLong": "Salut, {{pokemonName}} !",
|
||||
"thisIsWhereWePart": "C’est là qu’on se sépare, {{pokemonName}}!",
|
||||
"thisIsWhereWePart": "C’est là qu’on se sépare, {{pokemonName}} !",
|
||||
"illMissYou": "Tu vas me manquer, {{pokemonName}} !",
|
||||
"illNeverForgetYou": "Je ne t’oublierai pas, {{pokemonName}} !",
|
||||
"untilWeMeetAgain": "À la prochaine, {{pokemonName}} !",
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "Un vent mystérieux se lève !",
|
||||
"strongWindsLapseMessage": "Le vent mystérieux souffle violemment !",
|
||||
"strongWindsEffectMessage": "Le courant aérien mystérieux affaiblit l’attaque !",
|
||||
"strongWindsClearMessage": "Le vent mystérieux s’est dissipé…"
|
||||
};
|
||||
|
|
|
@ -5,8 +5,8 @@ export const battle: SimpleTranslationEntries = {
|
|||
"trainerAppeared": "{{trainerName}}\nvuole combattere!",
|
||||
"trainerAppearedDouble": "{{trainerName}}\nvogliono combattere!",
|
||||
"trainerSendOut": "{{trainerName}} manda in campo\n{{pokemonName}}!",
|
||||
"singleWildAppeared": "Appare {{pokemonName}} selvatico!",
|
||||
"multiWildAppeared": "Appaiono {{pokemonName1}}\ne {{pokemonName2}} salvatici!",
|
||||
"singleWildAppeared": "È apparso {{pokemonName}} selvatico!",
|
||||
"multiWildAppeared": "Sono apparsi {{pokemonName1}}\ne {{pokemonName2}} salvatici!",
|
||||
"playerComeBack": "Rientra, {{pokemonName}}!",
|
||||
"trainerComeBack": "{{trainerName}} ha ritirato {{pokemonName}}!",
|
||||
"playerGo": "Vai! {{pokemonName}}!",
|
||||
|
@ -25,6 +25,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "Non ha effetto su {{pokemonName}}!",
|
||||
"hitResultOneHitKO": "KO con un colpo!",
|
||||
"attackFailed": "Ma ha fallito!",
|
||||
"attackMissed": "{{pokemonNameWithAffix}}\nevita l’attacco!",
|
||||
"attackHitsCount": "Colpito {{count}} volta/e!",
|
||||
"rewardGain": "You received\n{{modifierName}}!",
|
||||
"expGain": "{{pokemonName}} ha guadagnato\n{{exp}} Punti Esperienza!",
|
||||
|
@ -43,10 +44,10 @@ export const battle: SimpleTranslationEntries = {
|
|||
"moveNotImplemented": "{{moveName}} non è ancora implementata e non può essere selezionata.",
|
||||
"moveNoPP": "Non ci sono PP rimanenti\nper questa mossa!",
|
||||
"moveDisabled": "{{moveName}} è disabilitata!",
|
||||
"noPokeballForce": "Una forza misteriosa\nimpedisce l'uso dell Poké Ball.",
|
||||
"noPokeballForce": "Una forza misteriosa\nimpedisce l'uso delle Poké Ball.",
|
||||
"noPokeballTrainer": "Non puoi catturare\nPokémon di altri allenatori!",
|
||||
"noPokeballMulti": "Puoi lanciare una Poké Ball\nquando rimane un solo Pokémon!",
|
||||
"noPokeballStrong": "Il Pokémon avversario è troppo forte per essere catturato!\nDevi prima indebolirlo!",
|
||||
"noPokeballMulti": "Puoi lanciare una Poké Ball\nsolo quando rimane un singolo Pokémon!",
|
||||
"noPokeballStrong": "Il Pokémon avversario è troppo forte per essere catturato!\nDevi prima indebolirlo.",
|
||||
"noEscapeForce": "Una forza misteriosa\nimpedisce la fuga.",
|
||||
"noEscapeTrainer": "Non puoi sottrarti\nalla lotta con un'allenatore!",
|
||||
"noEscapePokemon": "{{moveName}} di {{pokemonName}}\npreviene la {{escapeVerb}}!",
|
||||
|
@ -54,11 +55,11 @@ export const battle: SimpleTranslationEntries = {
|
|||
"runAwayCannotEscape": "Non puoi fuggire!",
|
||||
"escapeVerbSwitch": "cambiando",
|
||||
"escapeVerbFlee": "fuggendo",
|
||||
"notDisabled": "{{pokemonName}}'s {{moveName}} non è più\ndisabilitata!",
|
||||
"notDisabled": "{{moveName}} di {{pokemonName}} non è più\ndisabilitata!",
|
||||
"turnEndHpRestore": "{{pokemonName}}'s HP was restored.",
|
||||
"hpIsFull": "{{pokemonName}}'s\nHP is full!",
|
||||
"skipItemQuestion": "Sei sicuro di non voler prendere nessun oggetto?",
|
||||
"eggHatching": "Oh!",
|
||||
"eggHatching": "Oh?",
|
||||
"ivScannerUseQuestion": "Vuoi usare lo scanner di IV su {{pokemonName}}?",
|
||||
"stealEatBerry": "{{pokemonName}} stole and ate\n{{targetName}}'s {{berryName}}!",
|
||||
"wildPokemonWithAffix": "{{pokemonName}} selvatico",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Music",
|
||||
"music": "Music: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "B2W2 Kanto Champion Battle",
|
||||
"battle_johto_champion": "B2W2 Johto Champion Battle",
|
||||
|
|
|
@ -6,18 +6,18 @@ export const egg: SimpleTranslationEntries = {
|
|||
"greatTier": "Raro",
|
||||
"ultraTier": "Epico",
|
||||
"masterTier": "Leggendario",
|
||||
"hatchWavesMessageSoon": "Si sentono dei suoni provenienti dall'interno! Si schiuderà presto!",
|
||||
"hatchWavesMessageSoon": "Si sentono dei rumori provenienti dall'interno. Si schiuderà presto!",
|
||||
"hatchWavesMessageClose": "Sembra muoversi di tanto in tanto. Potrebbe essere prossimo alla schiusa.",
|
||||
"hatchWavesMessageNotClose": "Cosa uscirà da qui? Non sembra si schiuderà presto.",
|
||||
"hatchWavesMessageLongTime": "Sembra che questo uovo impiegherà molto tempo per schiudersi.",
|
||||
"gachaTypeLegendary": "Tasso dei Leggendari Aumentato",
|
||||
"gachaTypeMove": "Tasso delle Mosse Rare delle Uova Aumentato",
|
||||
"gachaTypeShiny": "Tasso degli Shiny Aumentato",
|
||||
"selectMachine": "Seleziona un distributore.",
|
||||
"notEnoughVouchers": "Non hai abbastanza Biglietti!",
|
||||
"tooManyEggs": "Hai troppe Uova!",
|
||||
"pull": "Tiro",
|
||||
"pulls": "Tiri",
|
||||
"hatchWavesMessageNotClose": "Cosa uscirà da qui? Pare che non si schiuderà presto.",
|
||||
"hatchWavesMessageLongTime": "Sembra che questo uovo impiegherà ancora molto tempo per schiudersi.",
|
||||
"gachaTypeLegendary": "Tasso dei leggendari aumentato",
|
||||
"gachaTypeMove": "Tasso delle mosse rare da uova aumentato",
|
||||
"gachaTypeShiny": "Tasso degli shiny aumentato",
|
||||
"selectMachine": "Seleziona un macchinario.",
|
||||
"notEnoughVouchers": "Non hai abbastanza biglietti!",
|
||||
"tooManyEggs": "Hai troppe uova!",
|
||||
"pull": "Estrazione",
|
||||
"pulls": "Estrazioni",
|
||||
"sameSpeciesEgg": "{{species}} will hatch from this egg!",
|
||||
"hatchFromTheEgg": "Dall’Uovo è nato {{pokemonName}}!",
|
||||
"eggMoveUnlock": "Egg Move unlocked: {{moveName}}",
|
||||
|
|
|
@ -2,23 +2,23 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
|||
|
||||
export const menuUiHandler: SimpleTranslationEntries = {
|
||||
"GAME_SETTINGS": "Impostazioni",
|
||||
"ACHIEVEMENTS": "Trofei",
|
||||
"ACHIEVEMENTS": "Obiettivi",
|
||||
"STATS": "Statistiche",
|
||||
"VOUCHERS": "Biglietti",
|
||||
"EGG_LIST": "Lista Uova",
|
||||
"EGG_GACHA": "Gacha Uova",
|
||||
"MANAGE_DATA": "Gestisci Dati",
|
||||
"EGG_LIST": "Lista uova",
|
||||
"EGG_GACHA": "Macchine uova",
|
||||
"MANAGE_DATA": "Gestisci dati",
|
||||
"COMMUNITY": "Community",
|
||||
"SAVE_AND_QUIT": "Salva ed Esci",
|
||||
"SAVE_AND_QUIT": "Salva ed esci",
|
||||
"LOG_OUT": "Disconnettiti",
|
||||
"slot": "Slot {{slotNumber}}",
|
||||
"importSession": "Importa Sessione",
|
||||
"importSession": "Importa sessione",
|
||||
"importSlotSelect": "Seleziona uno slot in cui importare.",
|
||||
"exportSession": "Esporta Sessione",
|
||||
"exportSession": "Esporta sessione",
|
||||
"exportSlotSelect": "Seleziona uno slot da cui esportare.",
|
||||
"importData": "Importa Dati",
|
||||
"exportData": "Esporta Dati",
|
||||
"importData": "Importa dati",
|
||||
"exportData": "Esporta dati",
|
||||
"cancel": "Annulla",
|
||||
"losingProgressionWarning": "Perderai tutti i progressi dall'inizio della battaglia. Procedere?",
|
||||
"losingProgressionWarning": "Perderai tutti i progressi dall'inizio della battaglia. Confermi?",
|
||||
"noEggs": "You are not hatching\nany eggs at the moment!"
|
||||
} as const;
|
||||
|
|
|
@ -13,18 +13,18 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
"PokemonHeldItemModifierType": {
|
||||
extra: {
|
||||
"inoperable": "{{pokemonName}} non può prendere\nquesto oggetto!",
|
||||
"tooMany": "{{pokemonName}} ne ha troppi\ndi questo oggetto!",
|
||||
"tooMany": "{{pokemonName}} possiede già\nquesto oggetto in abbondanza.",
|
||||
}
|
||||
},
|
||||
"PokemonHpRestoreModifierType": {
|
||||
description: "Restituisce {{restorePoints}} PS o {{restorePercent}}% PS ad un Pokémon, a seconda del valore più alto.",
|
||||
extra: {
|
||||
"fully": "Restituisce tutti i PS ad un Pokémon.",
|
||||
"fullyWithStatus": "Restituisce tutti i PS ad un Pokémon e lo cura da ogni stato.",
|
||||
"fullyWithStatus": "Restituisce tutti i PS ad un Pokémon e lo cura da ogni problema di stato.",
|
||||
}
|
||||
},
|
||||
"PokemonReviveModifierType": {
|
||||
description: "Rianima un Pokémon esausto e gli restituisce il {{restorePercent}}% PS.",
|
||||
description: "Rianima un Pokémon esausto e gli restituisce il {{restorePercent}}% dei PS totali.",
|
||||
},
|
||||
"PokemonStatusHealModifierType": {
|
||||
description: "Cura tutti i problemi di stato di un Pokémon.",
|
||||
|
@ -46,7 +46,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
},
|
||||
"PokemonNatureChangeModifierType": {
|
||||
name: "Menta {{natureName}}.",
|
||||
description: "Cambia la natura del Pokémon in {{natureName}} e sblocca la natura per il Pokémon iniziale.",
|
||||
description: "Cambia la natura del Pokémon in {{natureName}} e sblocca la natura nel menu degli starter.",
|
||||
},
|
||||
"DoubleBattleChanceBoosterModifierType": {
|
||||
description: "Raddoppia la possibilità di imbattersi in doppie battaglie per {{battleCount}} battaglie.",
|
||||
|
@ -67,7 +67,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
description: "Aumenta {{statName}} di base del possessore del 10%.",
|
||||
},
|
||||
"AllPokemonFullHpRestoreModifierType": {
|
||||
description: "Recupera il 100% dei PS per tutti i Pokémon.",
|
||||
description: "Restituisce il 100% dei PS a tutti i Pokémon.",
|
||||
},
|
||||
"AllPokemonFullReviveModifierType": {
|
||||
description: "Rianima tutti i Pokémon esausti restituendogli tutti i PS.",
|
||||
|
@ -75,7 +75,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
"MoneyRewardModifierType": {
|
||||
description: "Garantisce una {{moneyMultiplier}} quantità di soldi (₽{{moneyAmount}}).",
|
||||
extra: {
|
||||
"small": "poca",
|
||||
"small": "contenuta",
|
||||
"moderate": "moderata",
|
||||
"large": "grande",
|
||||
},
|
||||
|
@ -90,7 +90,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
description: "Aumenta del 50% il guadagno di amicizia per vittoria.",
|
||||
},
|
||||
"PokemonMoveAccuracyBoosterModifierType": {
|
||||
description: "Aumenta l'accuratezza delle mosse di {{accuracyAmount}} (massimo 100).",
|
||||
description: "Aumenta la precisione delle mosse di {{accuracyAmount}} (massimo 100).",
|
||||
},
|
||||
"PokemonMultiHitModifierType": {
|
||||
description: "Gli attacchi colpiscono una volta in più al costo di una riduzione di potenza del 60/75/82,5% per mossa.",
|
||||
|
@ -117,7 +117,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
description: "Teracristallizza in {{teraType}} il possessore per massimo 10 battaglie.",
|
||||
},
|
||||
"ContactHeldItemTransferChanceModifierType": {
|
||||
description: "Quando si attacca, c'è una probabilità del {{chancePercent}}% che l'oggetto in possesso del nemico venga rubato.",
|
||||
description: "Quando il possessore attacca, c'è una probabilità del {{chancePercent}}% che l'oggetto in possesso del nemico gli venga rubato.",
|
||||
},
|
||||
"TurnHeldItemTransferModifierType": {
|
||||
description: "Ogni turno, il possessore acquisisce un oggetto posseduto dal nemico.",
|
||||
|
@ -129,72 +129,71 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
description: "Aggiunge una probabilità del {{probabilitàPercent}}% di resistere ad un colpo.",
|
||||
},
|
||||
|
||||
"RARE_CANDY": { name: "Caramella Rara" },
|
||||
"RARER_CANDY": { name: "Caramella Molto Rara" },
|
||||
"RARE_CANDY": { name: "Caramella rara" },
|
||||
"RARER_CANDY": { name: "Caramella molto rara" },
|
||||
|
||||
"MEGA_BRACELET": { name: "Megapolsiera", description: "Le Megapietre sono disponibili." },
|
||||
"DYNAMAX_BAND": { name: "Polsino Dynamax", description: "I Fungomax sono disponibili." },
|
||||
"TERA_ORB": { name: "Terasfera", description: "I Teraliti sono disponibili." },
|
||||
"MEGA_BRACELET": { name: "Megapolsiera", description: "Le megapietre diventano disponibili." },
|
||||
"DYNAMAX_BAND": { name: "Polsino Dynamax", description: "I fungomax diventano disponibili." },
|
||||
"TERA_ORB": { name: "Terasfera", description: "I teraliti diventano disponibili." },
|
||||
|
||||
"MAP": { name: "Mappa", description: "Permette di scegliere la propria strada a un bivio." },
|
||||
|
||||
"POTION": { name: "Pozione" },
|
||||
"SUPER_POTION": { name: "Superpozione" },
|
||||
"HYPER_POTION": { name: "Iperpozione" },
|
||||
"MAX_POTION": { name: "Pozione Max" },
|
||||
"FULL_RESTORE": { name: "Ricarica Totale" },
|
||||
"MAX_POTION": { name: "Pozione max" },
|
||||
"FULL_RESTORE": { name: "Ricarica totale" },
|
||||
|
||||
"REVIVE": { name: "Revitalizzante" },
|
||||
"MAX_REVIVE": { name: "Revitalizzante Max" },
|
||||
"MAX_REVIVE": { name: "Revitalizzante max" },
|
||||
|
||||
"FULL_HEAL": { name: "Cura Totale" },
|
||||
"FULL_HEAL": { name: "Cura totale" },
|
||||
|
||||
"SACRED_ASH": { name: "Cenere Magica" },
|
||||
"SACRED_ASH": { name: "Cenere magica" },
|
||||
|
||||
"REVIVER_SEED": { name: "Revitalseme", description: "Il possessore recupera 1/2 di PS in caso di svenimento." },
|
||||
"REVIVER_SEED": { name: "Revitalseme", description: "Il possessore recupera 1/2 di PS in caso di KO." },
|
||||
|
||||
"ETHER": { name: "Etere" },
|
||||
"MAX_ETHER": { name: "Etere Max" },
|
||||
"MAX_ETHER": { name: "Etere max" },
|
||||
|
||||
"ELIXIR": { name: "Elisir" },
|
||||
"MAX_ELIXIR": { name: "Elisir Max" },
|
||||
"MAX_ELIXIR": { name: "Elisir max" },
|
||||
|
||||
"PP_UP": { name: "PP-su" },
|
||||
"PP_MAX": { name: "PP-max" },
|
||||
|
||||
"LURE": { name: "Profumo Invito" },
|
||||
"SUPER_LURE": { name: "Profumo Invito Super" },
|
||||
"MAX_LURE": { name: "Profumo Invito Max" },
|
||||
"LURE": { name: "Esca" },
|
||||
"SUPER_LURE": { name: "Super esca" },
|
||||
"MAX_LURE": { name: "Esca max" },
|
||||
|
||||
"MEMORY_MUSHROOM": { name: "Fungo della Memoria", description: "Ricorda la mossa dimenticata di un Pokémon." },
|
||||
"MEMORY_MUSHROOM": { name: "Fungo della memoria", description: "Permette di insegnare nuovamente una mossa dimenticata ad un Pokémon." },
|
||||
|
||||
"EXP_SHARE": { name: "Condividi Esperienza", description: "Tutti i Pokémon della squadra ricevono il 20% dei Punti Esperienza dalla lotta anche se non vi hanno partecipato." },
|
||||
"EXP_BALANCE": { name: "Bilancia Esperienza", description: "Bilancia i Punti Esperienza ricevuti verso i Pokémon del gruppo di livello inferiore." },
|
||||
"EXP_SHARE": { name: "Condividi esperienza", description: "Tutti i Pokémon della squadra ricevono il 20% dei Punti Esperienza dalla lotta, anche se non vi hanno partecipato." },
|
||||
"EXP_BALANCE": { name: "Bilancia esperienza", description: "Bilancia i Punti Esperienza ricevuti verso i Pokémon della squadra di livello inferiore." },
|
||||
|
||||
"OVAL_CHARM": { name: "Ovamuleto", description: "Quando più Pokémon partecipano a una battaglia, ognuno di essi riceve il 10% in più dell'esperienza totale." },
|
||||
|
||||
"EXP_CHARM": { name: "Esperienzamuleto" },
|
||||
"SUPER_EXP_CHARM": { name: "Esperienzamuleto Super" },
|
||||
"GOLDEN_EXP_CHARM": { name: "Esperienzamuleto Oro" },
|
||||
"SUPER_EXP_CHARM": { name: "Esperienzamuleto super" },
|
||||
"GOLDEN_EXP_CHARM": { name: "Esperienzamuleto dorato" },
|
||||
|
||||
"LUCKY_EGG": { name: "Uovo Fortunato" },
|
||||
"GOLDEN_EGG": { name: "Uovo d'Oro" },
|
||||
"LUCKY_EGG": { name: "Fortunuovo" },
|
||||
"GOLDEN_EGG": { name: "Uovo dorato" },
|
||||
|
||||
"SOOTHE_BELL": { name: "Calmanella" },
|
||||
|
||||
"EVIOLITE": { name: "Evolcondensa", description: "Misteriosa materia evolutiva. Aumenta la Difesa e la Difesa Speciale di un Pokémon che può ancora evolversi." },
|
||||
|
||||
"SOUL_DEW": { name: "Cuorugiada", description: "Aumenta del 10% l'influenza della natura di un Pokémon sulle sue statistiche (Aggiuntivo)." },
|
||||
"SOUL_DEW": { name: "Cuorugiada", description: "Aumenta del 10% l'influenza della natura di un Pokémon sulle sue statistiche (cumulativo)." },
|
||||
|
||||
"NUGGET": { name: "Pepita" },
|
||||
"BIG_NUGGET": { name: "Granpepita" },
|
||||
"RELIC_GOLD": { name: "Dobloantico" },
|
||||
|
||||
"AMULET_COIN": { name: "Monetamuleto", description: "Aumenta le ricompense in denaro del 20%." },
|
||||
"GOLDEN_PUNCH": { name: "Pugno Dorato", description: "Garantisce il 50% dei danni inflitti come denaro." },
|
||||
"COIN_CASE": { name: " Salvadanaio", description: "Dopo ogni 10° battaglia, riceverete il 10% del vostro denaro in interessi." },
|
||||
"GOLDEN_PUNCH": { name: "Pugno dorato", description: "Fornisce il 50% dei danni inflitti sottoforma di denaro." },
|
||||
"COIN_CASE": { name: "Salvadanaio", description: "Dopo ogni 10° battaglia, fornisce il 10% del proprio denaro in interessi." },
|
||||
|
||||
"LOCK_CAPSULE": { name: "Capsula Scrigno", description: "Permette di bloccare le rarità degli oggetti quando si fa un reroll degli oggetti." },
|
||||
"LOCK_CAPSULE": { name: "Capsula scrigno", description: "Permette di bloccare le rarità degli oggetti quando si fa un reroll (i costi variano in base alle rarità)." },
|
||||
|
||||
"GRIP_CLAW": { name: "Presartigli" },
|
||||
"WIDE_LENS": { name: "Grandelente" },
|
||||
|
@ -202,18 +201,18 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
"MULTI_LENS": { name: "Multilente" },
|
||||
|
||||
"HEALING_CHARM": { name: "Curamuleto", description: "Aumenta del 10% l'efficacia delle mosse e degli oggetti che ripristinano i PS (escluse le rianimazioni)." },
|
||||
"CANDY_JAR": { name: "Barattolo di caramelle", description: "Aumenta di 1 il numero di livelli aggiunti dalle Caramelle Rare." },
|
||||
"CANDY_JAR": { name: "Barattolo di caramelle", description: "Aumenta di 1 il numero di livelli aggiunti dalle caramelle rare." },
|
||||
|
||||
"BERRY_POUCH": { name: "Porta Bacche", description: "Aggiunge il 30% di possibilità che una bacca usata non venga consumata." },
|
||||
"BERRY_POUCH": { name: "Porta bacche", description: "Aggiunge il 30% di possibilità che una bacca usata non venga consumata." },
|
||||
|
||||
"FOCUS_BAND": { name: "Bandana", description: "Chi ce l'ha ottiene il 10% di possibilità aggiuntivo di evitare un potenziale KO e rimanere con un solo PS." },
|
||||
"FOCUS_BAND": { name: "Bandana", description: "Il possessore ottiene il 10% di possibilità aggiuntivo di evitare un potenziale KO e rimanere con un solo PS." },
|
||||
|
||||
"QUICK_CLAW": { name: "Rapidartigli", description: "Aggiunge una probabilità del 10% di muoversi per primi, indipendentemente dalla velocità (dopo la priorità)." },
|
||||
"QUICK_CLAW": { name: "Rapidartigli", description: "Aggiunge una probabilità del 10% di muoversi per primi, indipendentemente dalla velocità (priorità escluse)." },
|
||||
|
||||
"KINGS_ROCK": { name: "Roccia di re", description: "Aggiunge il 10% di possibilità che una mossa d'attacco faccia tentennare l'avversario." },
|
||||
|
||||
"LEFTOVERS": { name: "Avanzi", description: "Ripristina 1/16 dei PS massimi di un Pokémon ogni turno." },
|
||||
"SHELL_BELL": { name: "Conchinella", description: "Guarisce 1/8 del danno inflitto a un Pokémon." },
|
||||
"SHELL_BELL": { name: "Conchinella", description: "Cura il possessore di 1/8 del danno inflitto ad un Pokémon." },
|
||||
|
||||
"TOXIC_ORB": { name: "Tossicsfera", description: "Sfera bizzarra che iperavvelena chi l’ha con sé in una lotta." },
|
||||
"FLAME_ORB": { name: "Fiammosfera", description: "Sfera bizzarra che procura una scottatura a chi l’ha con sé in una lotta." },
|
||||
|
@ -223,22 +222,22 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
"SHINY_CHARM": { name: "Cromamuleto", description: "Misterioso amuleto luminoso che aumenta la probabilità di incontrare Pokémon cromatici." },
|
||||
"ABILITY_CHARM": { name: "Abilitamuleto", description: "Aumenta drasticamente la possibilità che un Pokémon selvatico abbia un'abilità nascosta." },
|
||||
|
||||
"IV_SCANNER": { name: "Scanner IV", description: "Permette di scansionare gli IV dei Pokémon selvatici. Vengono rivelati 2 IV per pila. I migliori IV vengono mostrati per primi." },
|
||||
"IV_SCANNER": { name: "Scanner IV", description: "Permette di scansionare gli IV dei Pokémon selvatici. Vengono rivelati 2 IV per ogni scanner. I migliori IV vengono mostrati per primi." },
|
||||
|
||||
"DNA_SPLICERS": { name: "Cuneo DNA" },
|
||||
|
||||
"MINI_BLACK_HOLE": { name: "Piccolo Buco Nero" },
|
||||
"MINI_BLACK_HOLE": { name: "Piccolo buco nero" },
|
||||
|
||||
"GOLDEN_POKEBALL": { name: "Poké Ball Oro", description: "Aggiunge 1 opzione di oggetto extra alla fine di ogni battaglia." },
|
||||
"GOLDEN_POKEBALL": { name: "Poké Ball dorata", description: "Aggiunge 1 opzione di oggetto extra alla fine di ogni battaglia." },
|
||||
|
||||
"ENEMY_DAMAGE_BOOSTER": { name: "Gettone del Danno", description: "Aumenta il danno del 5%." },
|
||||
"ENEMY_DAMAGE_REDUCTION": { name: "Gettone della Protezione", description: "Riduce i danni ricevuti del 2.5%." },
|
||||
"ENEMY_HEAL": { name: "Gettone del Recupero", description: "Cura il 2% dei PS massimi ogni turno." },
|
||||
"ENEMY_ATTACK_POISON_CHANCE": { name: "Gettone del Veleno" },
|
||||
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Gettone della Paralisi" },
|
||||
"ENEMY_ATTACK_BURN_CHANCE": { name: "Gettone della Bruciatura" },
|
||||
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone Guarigione Completa", description: "Aggiunge una probabilità del 2.5% a ogni turno di curare una condizione di stato." },
|
||||
"ENEMY_ENDURE_CHANCE": { name: "Gettone di Resistenza" },
|
||||
"ENEMY_DAMAGE_BOOSTER": { name: "Gettone del danno", description: "Aumenta i danni inflitti del 5%." },
|
||||
"ENEMY_DAMAGE_REDUCTION": { name: "Gettone della protezione", description: "Riduce i danni ricevuti del 2.5%." },
|
||||
"ENEMY_HEAL": { name: "Gettone del recupero", description: "Cura il 2% dei PS massimi ogni turno." },
|
||||
"ENEMY_ATTACK_POISON_CHANCE": { name: "Gettone del veleno" },
|
||||
"ENEMY_ATTACK_PARALYZE_CHANCE": { name: "Gettone della paralisi" },
|
||||
"ENEMY_ATTACK_BURN_CHANCE": { name: "Gettone della bruciatura" },
|
||||
"ENEMY_STATUS_EFFECT_HEAL_CHANCE": { name: "Gettone guarigione completa", description: "Aggiunge una probabilità del 2.5% a ogni turno di guarire da un problema di stato." },
|
||||
"ENEMY_ENDURE_CHANCE": { name: "Gettone di resistenza" },
|
||||
"ENEMY_FUSED_CHANCE": { name: "Gettone della fusione", description: "Aggiunge l'1% di possibilità che un Pokémon selvatico sia una fusione." },
|
||||
},
|
||||
SpeciesBoosterItem: {
|
||||
|
@ -258,14 +257,14 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
},
|
||||
|
||||
TempBattleStatBoosterStatName: {
|
||||
"ATK": "Attack",
|
||||
"DEF": "Defense",
|
||||
"SPATK": "Sp. Atk",
|
||||
"SPDEF": "Sp. Def",
|
||||
"SPD": "Speed",
|
||||
"ACC": "Accuracy",
|
||||
"CRIT": "Critical Hit Ratio",
|
||||
"EVA": "Evasiveness",
|
||||
"ATK": "Attacco",
|
||||
"DEF": "Difesa",
|
||||
"SPATK": "Att. Speciale",
|
||||
"SPDEF": "Dif. Speciale",
|
||||
"SPD": "Velocità",
|
||||
"ACC": "Precisione",
|
||||
"CRIT": "Tasso di brutti colpi",
|
||||
"EVA": "Elusione",
|
||||
"DEFAULT": "???",
|
||||
},
|
||||
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "È apparsa una corrente d'aria misteriosa!",
|
||||
"strongWindsLapseMessage": "La corrente d'aria soffia intensamente.",
|
||||
"strongWindsEffectMessage": "La corrente misteriosa indebolisce l’attacco!",
|
||||
"strongWindsClearMessage": "La corrente d'aria è cessata."
|
||||
};
|
||||
|
|
|
@ -24,7 +24,8 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNotVeryEffective": "효과가 별로인 듯하다…",
|
||||
"hitResultNoEffect": "{{pokemonName}}에게는\n효과가 없는 것 같다…",
|
||||
"hitResultOneHitKO": "일격필살!",
|
||||
"attackFailed": "하지만 실패했다!",
|
||||
"attackFailed": "그러나 실패하고 말았다!!",
|
||||
"attackMissed": "{{pokemonNameWithAffix}}에게는\n맞지 않았다!",
|
||||
"attackHitsCount": "{{count}}번 맞았다!",
|
||||
"rewardGain": "{{modifierName}}[[를]] 받았다!",
|
||||
"expGain": "{{pokemonName}}[[는]]\n{{exp}} 경험치를 얻었다!",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Music",
|
||||
"music": "Music: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "BW2 관동 챔피언 배틀",
|
||||
"battle_johto_champion": "BW2 성도 챔피언 배틀",
|
||||
|
@ -62,7 +62,7 @@ export const bgmName: SimpleTranslationEntries = {
|
|||
"battle_legendary_calyrex": "SWSH 버드렉스 배틀",
|
||||
"battle_legendary_birds_galar": "SWSH 가라르 전설의 새 배틀",
|
||||
"battle_legendary_ruinous": "SV 재앙의 보물 배틀",
|
||||
"battle_legendary_kor_mir": "SV Depths of Area Zero Battle",
|
||||
"battle_legendary_kor_mir": "SV 에리어 제로 배틀",
|
||||
"battle_legendary_loyal_three": "SV 세벗들 배틀",
|
||||
"battle_legendary_ogerpon": "SV 오거폰 배틀",
|
||||
"battle_legendary_terapagos": "SV 테라파고스 배틀",
|
||||
|
@ -74,16 +74,16 @@ export const bgmName: SimpleTranslationEntries = {
|
|||
"battle_wild": "BW 야생 포켓몬 배틀",
|
||||
"battle_wild_strong": "BW 강한 야생 포켓몬 조우 배틀",
|
||||
"end_summit": "불가사의 던전 구조대 DX 천공의 탑 꼭대기",
|
||||
"battle_rocket_grunt": "HGSS Team Rocket Battle",
|
||||
"battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle",
|
||||
"battle_galactic_grunt": "BDSP Team Galactic Battle",
|
||||
"battle_rocket_grunt": "HGSS 로켓단 배틀",
|
||||
"battle_aqua_magma_grunt": "ORAS 아쿠아단 & 마그마단 배틀",
|
||||
"battle_galactic_grunt": "BDSP 갤럭시단 배틀",
|
||||
"battle_plasma_grunt": "BW 플라스마단 배틀",
|
||||
"battle_flare_grunt": "XY Team Flare Battle",
|
||||
"battle_rocket_boss": "USUM Giovanni Battle",
|
||||
"battle_aqua_magma_boss": "ORAS Archie & Maxie Battle",
|
||||
"battle_galactic_boss": "BDSP Cyrus Battle",
|
||||
"battle_plasma_boss": "B2W2 Ghetsis Battle",
|
||||
"battle_flare_boss": "XY Lysandre Battle",
|
||||
"battle_flare_grunt": "XY 플레어단 배틀",
|
||||
"battle_rocket_boss": "USUM 비주기 배틀",
|
||||
"battle_aqua_magma_boss": "ORAS 아강 & 마적 배틀",
|
||||
"battle_galactic_boss": "BDSP 태홍 배틀",
|
||||
"battle_plasma_boss": "B2W2 게치스 배틀",
|
||||
"battle_flare_boss": "XY 플라드리 배틀",
|
||||
|
||||
// Biome Music
|
||||
"abyss": "불가사의 던전 하늘의 탐험대 어둠의 화구",
|
||||
|
|
|
@ -2,7 +2,7 @@ import { TranslationEntries } from "#app/interfaces/locales";
|
|||
|
||||
export const challenges: TranslationEntries = {
|
||||
"title": "챌린지 조건 설정",
|
||||
"illegalEvolution": "{{pokemon}} changed into an ineligble pokémon\nfor this challenge!",
|
||||
"illegalEvolution": "{{pokemon}}[[는]] 현재의 챌린지에\n부적합한 포켓몬이 되었습니다!",
|
||||
"singleGeneration": {
|
||||
"name": "단일 세대",
|
||||
"desc": "{{gen}}의 포켓몬만 사용할 수 있습니다.",
|
||||
|
|
|
@ -20,5 +20,5 @@ export const menuUiHandler: SimpleTranslationEntries = {
|
|||
"exportData": "데이터 내보내기",
|
||||
"cancel": "취소",
|
||||
"losingProgressionWarning": "전투 시작으로부터의 진행 상황을 잃게 됩니다. 계속하시겠습니까?",
|
||||
"noEggs": "You are not hatching\nany eggs at the moment!"
|
||||
"noEggs": "부화중인 알이 없습니다!"
|
||||
} as const;
|
||||
|
|
|
@ -35,8 +35,8 @@ export const partyUiHandler: SimpleTranslationEntries = {
|
|||
"cancel": "그만둔다",
|
||||
|
||||
// Slot TM text
|
||||
"able": "배울 수 있다",
|
||||
"notAble": "배울 수 없다",
|
||||
"able": "배운다!",
|
||||
"notAble": "배우지 못함",
|
||||
"learned": "알고 있다",
|
||||
|
||||
// Releasing messages
|
||||
|
|
|
@ -41,5 +41,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "수수께끼의 난기류가\n비행포켓몬을 지킨다!",
|
||||
"strongWindsLapseMessage": "수수께끼의 난기류가 강렬하게 불고 있다",
|
||||
"strongWindsEffectMessage": "수수께끼의 난기류가 공격을 약하게 만들었다!",
|
||||
"strongWindsClearMessage": "수수께끼의 난기류가 멈췄다!" // 임의번역
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "Isso não afeta {{pokemonName}}!",
|
||||
"hitResultOneHitKO": "Foi um nocaute de um golpe!",
|
||||
"attackFailed": "Mas falhou!",
|
||||
"attackMissed": "{{pokemonNameWithAffix}} desviou do ataque!",
|
||||
"attackHitsCount": "Acertou {{count}} vezes.",
|
||||
"rewardGain": "Você recebeu\n{{modifierName}}!",
|
||||
"expGain": "{{pokemonName}} ganhou\n{{exp}} pontos de experiência.",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Music",
|
||||
"music": "Music: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "B2W2 Kanto Champion Battle",
|
||||
"battle_johto_champion": "B2W2 Johto Champion Battle",
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "Ventos fortes apareceram!",
|
||||
"strongWindsLapseMessage": "Os ventos fortes continuam.",
|
||||
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
|
||||
"strongWindsClearMessage": "Os ventos fortes diminuíram.",
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "对{{pokemonName}}没有效果!!",
|
||||
"hitResultOneHitKO": "一击必杀!",
|
||||
"attackFailed": "但是失败了!",
|
||||
"attackMissed": "没有命中{{pokemonNameWithAffix}}!",
|
||||
"attackHitsCount": "击中{{count}}次!",
|
||||
"rewardGain": "你获得了\n{{modifierName}}!",
|
||||
"expGain": "{{pokemonName}}获得了 {{exp}} 点经验值!",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "BGM",
|
||||
"music": "BGM: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "黑2白2「决战!关都冠军」",
|
||||
"battle_johto_champion": "黑2白2「决战!城都冠军」",
|
||||
|
|
|
@ -14,7 +14,7 @@ export const partyUiHandler: SimpleTranslationEntries = {
|
|||
"TRANSFER": "交换",
|
||||
"ALL": "全部道具",
|
||||
"PASS_BATON": "接棒",
|
||||
"UNPAUSE_EVOLUTION": "接触进化暂停",
|
||||
"UNPAUSE_EVOLUTION": "解除进化暂停",
|
||||
"REVIVE": "复活",
|
||||
|
||||
"choosePokemon": "选择一只宝可梦。",
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "吹起了神秘的乱流!",
|
||||
"strongWindsLapseMessage": "神秘的乱流势头不减。",
|
||||
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
|
||||
"strongWindsClearMessage": "神秘的乱流停止了。"
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"hitResultNoEffect": "對 {{pokemonName}} 沒有效果!",
|
||||
"hitResultOneHitKO": "一擊切殺!",
|
||||
"attackFailed": "但是失敗了!",
|
||||
"attackMissed": "沒有命中{{pokemonNameWithAffix}}!",
|
||||
"attackHitsCount": "擊中 {{count}} 次!",
|
||||
"rewardGain": "You received\n{{modifierName}}!",
|
||||
"expGain": "{{pokemonName}} 獲得了 {{exp}} 經驗值!",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SimpleTranslationEntries } from "#app/interfaces/locales";
|
||||
|
||||
export const bgmName: SimpleTranslationEntries = {
|
||||
"music": "Music",
|
||||
"music": "Music: ",
|
||||
"missing_entries" : "{{name}}",
|
||||
"battle_kanto_champion": "B2W2 Kanto Champion Battle",
|
||||
"battle_johto_champion": "B2W2 Johto Champion Battle",
|
||||
|
|
|
@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {
|
|||
|
||||
"strongWindsStartMessage": "吹起了神秘的亂流!",
|
||||
"strongWindsLapseMessage": "神秘的亂流勢頭不減。",
|
||||
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
|
||||
"strongWindsClearMessage": "神秘的亂流停止了。"
|
||||
};
|
||||
|
|
|
@ -2894,7 +2894,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||
if (!activeTargets.length || (!move.hasAttr(VariableTargetAttr) && !move.isMultiTarget() && !targetHitChecks[this.targets[0]])) {
|
||||
this.stopMultiHit();
|
||||
if (activeTargets.length) {
|
||||
this.scene.queueMessage(getPokemonMessage(user, "'s\nattack missed!"));
|
||||
this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: getPokemonNameWithAffix(this.getTarget()) }));
|
||||
moveHistoryEntry.result = MoveResult.MISS;
|
||||
applyMoveAttrs(MissEffectAttr, user, null, move);
|
||||
} else {
|
||||
|
@ -2912,7 +2912,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||
for (const target of targets) {
|
||||
if (!targetHitChecks[target.getBattlerIndex()]) {
|
||||
this.stopMultiHit(target);
|
||||
this.scene.queueMessage(getPokemonMessage(user, "'s\nattack missed!"));
|
||||
this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: getPokemonNameWithAffix(target) }));
|
||||
if (moveHistoryEntry.result === MoveResult.PENDING) {
|
||||
moveHistoryEntry.result = MoveResult.MISS;
|
||||
}
|
||||
|
@ -3616,7 +3616,9 @@ export class DamagePhase extends PokemonPhase {
|
|||
super.start();
|
||||
|
||||
if (this.damageResult === HitResult.ONE_HIT_KO) {
|
||||
if (this.scene.moveAnimations) {
|
||||
this.scene.toggleInvert(true);
|
||||
}
|
||||
this.scene.time.delayedCall(Utils.fixedInt(1000), () => {
|
||||
this.scene.toggleInvert(false);
|
||||
this.applyDamage();
|
||||
|
|
|
@ -316,10 +316,10 @@ export const achvs = {
|
|||
CATCH_LEGENDARY: new Achv("CATCH_LEGENDARY", "", "CATCH_LEGENDARY.description","mb", 100).setSecret(),
|
||||
SEE_SHINY: new Achv("SEE_SHINY", "", "SEE_SHINY.description","pb_gold", 75),
|
||||
SHINY_PARTY: new Achv("SHINY_PARTY", "", "SHINY_PARTY.description","shiny_charm", 100).setSecret(true),
|
||||
HATCH_MYTHICAL: new Achv("HATCH_MYTHICAL", "", "HATCH_MYTHICAL.description","pair_of_tickets", 75).setSecret(),
|
||||
HATCH_SUB_LEGENDARY: new Achv("HATCH_SUB_LEGENDARY","", "HATCH_SUB_LEGENDARY.description","mystic_ticket", 100).setSecret(),
|
||||
HATCH_LEGENDARY: new Achv("HATCH_LEGENDARY","", "HATCH_LEGENDARY.description","mystic_ticket", 125).setSecret(),
|
||||
HATCH_SHINY: new Achv("HATCH_SHINY","", "HATCH_SHINY.description","golden_mystic_ticket", 100).setSecret(),
|
||||
HATCH_MYTHICAL: new Achv("HATCH_MYTHICAL", "", "HATCH_MYTHICAL.description","mystery_egg", 75).setSecret(),
|
||||
HATCH_SUB_LEGENDARY: new Achv("HATCH_SUB_LEGENDARY","", "HATCH_SUB_LEGENDARY.description","oval_stone", 100).setSecret(),
|
||||
HATCH_LEGENDARY: new Achv("HATCH_LEGENDARY","", "HATCH_LEGENDARY.description","lucky_egg", 125).setSecret(),
|
||||
HATCH_SHINY: new Achv("HATCH_SHINY","", "HATCH_SHINY.description","golden_egg", 100).setSecret(),
|
||||
HIDDEN_ABILITY: new Achv("HIDDEN_ABILITY","", "HIDDEN_ABILITY.description","ability_charm", 75),
|
||||
PERFECT_IVS: new Achv("PERFECT_IVS","", "PERFECT_IVS.description","blunder_policy", 100),
|
||||
CLASSIC_VICTORY: new Achv("CLASSIC_VICTORY","", "CLASSIC_VICTORY.description","relic_crown", 150),
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import Phaser from "phaser";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import * as overrides from "#app/overrides";
|
||||
import { Species } from "#enums/species";
|
||||
import {
|
||||
TurnStartPhase,
|
||||
} from "#app/phases";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { getMovePosition } from "#app/test/utils/gameManagerUtils";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { allMoves } from "#app/data/move.js";
|
||||
|
||||
describe("Weather - Strong Winds", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(10);
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.TAILLOW);
|
||||
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DELTA_STREAM);
|
||||
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.THUNDERBOLT, Moves.ICE_BEAM, Moves.ROCK_SLIDE]);
|
||||
});
|
||||
|
||||
it("electric type move is not very effective on Rayquaza", async () => {
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RAYQUAZA);
|
||||
|
||||
await game.startBattle([Species.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon();
|
||||
const enemy = game.scene.getEnemyPokemon();
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.THUNDERBOLT));
|
||||
|
||||
await game.phaseInterceptor.to(TurnStartPhase);
|
||||
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.THUNDERBOLT].type, pikachu)).toBe(0.5);
|
||||
});
|
||||
|
||||
it("electric type move is neutral for flying type pokemon", async () => {
|
||||
await game.startBattle([Species.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon();
|
||||
const enemy = game.scene.getEnemyPokemon();
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.THUNDERBOLT));
|
||||
|
||||
await game.phaseInterceptor.to(TurnStartPhase);
|
||||
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.THUNDERBOLT].type, pikachu)).toBe(1);
|
||||
});
|
||||
|
||||
it("ice type move is neutral for flying type pokemon", async () => {
|
||||
await game.startBattle([Species.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon();
|
||||
const enemy = game.scene.getEnemyPokemon();
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.ICE_BEAM));
|
||||
|
||||
await game.phaseInterceptor.to(TurnStartPhase);
|
||||
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.ICE_BEAM].type, pikachu)).toBe(1);
|
||||
});
|
||||
|
||||
it("rock type move is neutral for flying type pokemon", async () => {
|
||||
await game.startBattle([Species.PIKACHU]);
|
||||
const pikachu = game.scene.getPlayerPokemon();
|
||||
const enemy = game.scene.getEnemyPokemon();
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.ROCK_SLIDE));
|
||||
|
||||
await game.phaseInterceptor.to(TurnStartPhase);
|
||||
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.ROCK_SLIDE].type, pikachu)).toBe(1);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,149 @@
|
|||
import {
|
||||
BattleStat,
|
||||
getBattleStatLevelChangeDescription,
|
||||
getBattleStatName,
|
||||
} from "#app/data/battle-stat.js";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { arrayOfRange, mockI18next } from "./utils/testUtils";
|
||||
|
||||
const TEST_BATTLE_STAT = -99 as unknown as BattleStat;
|
||||
const TEST_POKEMON = "Testmon";
|
||||
const TEST_STAT = "Teststat";
|
||||
|
||||
describe("battle-stat", () => {
|
||||
describe("getBattleStatName", () => {
|
||||
it("should return the correct name for each BattleStat", () => {
|
||||
mockI18next();
|
||||
|
||||
expect(getBattleStatName(BattleStat.ATK)).toBe("pokemonInfo:Stat.ATK");
|
||||
expect(getBattleStatName(BattleStat.DEF)).toBe("pokemonInfo:Stat.DEF");
|
||||
expect(getBattleStatName(BattleStat.SPATK)).toBe(
|
||||
"pokemonInfo:Stat.SPATK"
|
||||
);
|
||||
expect(getBattleStatName(BattleStat.SPDEF)).toBe(
|
||||
"pokemonInfo:Stat.SPDEF"
|
||||
);
|
||||
expect(getBattleStatName(BattleStat.SPD)).toBe("pokemonInfo:Stat.SPD");
|
||||
expect(getBattleStatName(BattleStat.ACC)).toBe("pokemonInfo:Stat.ACC");
|
||||
expect(getBattleStatName(BattleStat.EVA)).toBe("pokemonInfo:Stat.EVA");
|
||||
});
|
||||
|
||||
it("should fall back to ??? for an unknown BattleStat", () => {
|
||||
expect(getBattleStatName(TEST_BATTLE_STAT)).toBe("???");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getBattleStatLevelChangeDescription", () => {
|
||||
it("should return battle:statRose for +1", () => {
|
||||
mockI18next();
|
||||
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
1,
|
||||
true
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statRose");
|
||||
});
|
||||
|
||||
it("should return battle:statSharplyRose for +2", () => {
|
||||
mockI18next();
|
||||
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
2,
|
||||
true
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statSharplyRose");
|
||||
});
|
||||
|
||||
it("should return battle:statRoseDrastically for +3 to +6", () => {
|
||||
mockI18next();
|
||||
|
||||
arrayOfRange(3, 6).forEach((n) => {
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
n,
|
||||
true
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statRoseDrastically");
|
||||
});
|
||||
});
|
||||
|
||||
it("should return battle:statWontGoAnyHigher for 7 or higher", () => {
|
||||
mockI18next();
|
||||
|
||||
arrayOfRange(7, 10).forEach((n) => {
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
n,
|
||||
true
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statWontGoAnyHigher");
|
||||
});
|
||||
});
|
||||
|
||||
it("should return battle:statFell for -1", () => {
|
||||
mockI18next();
|
||||
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
1,
|
||||
false
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statFell");
|
||||
});
|
||||
|
||||
it("should return battle:statHarshlyFell for -2", () => {
|
||||
mockI18next();
|
||||
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
2,
|
||||
false
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statHarshlyFell");
|
||||
});
|
||||
|
||||
it("should return battle:statSeverelyFell for -3 to -6", () => {
|
||||
mockI18next();
|
||||
|
||||
arrayOfRange(3, 6).forEach((n) => {
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
n,
|
||||
false
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statSeverelyFell");
|
||||
});
|
||||
});
|
||||
|
||||
it("should return battle:statWontGoAnyLower for -7 or lower", () => {
|
||||
mockI18next();
|
||||
|
||||
arrayOfRange(7, 10).forEach((n) => {
|
||||
const message = getBattleStatLevelChangeDescription(
|
||||
TEST_POKEMON,
|
||||
TEST_STAT,
|
||||
n,
|
||||
false
|
||||
);
|
||||
|
||||
expect(message).toBe("battle:statWontGoAnyLower");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -7,9 +7,9 @@ import {
|
|||
getStatusEffectObtainText,
|
||||
getStatusEffectOverlapText,
|
||||
} from "#app/data/status-effect";
|
||||
import i18next, { ParseKeys } from "i18next";
|
||||
import i18next from "i18next";
|
||||
import { mockI18next } from "../utils/testUtils";
|
||||
|
||||
const tMock = (key: ParseKeys) => key;
|
||||
const pokemonName = "PKM";
|
||||
const sourceText = "SOURCE";
|
||||
|
||||
|
@ -22,7 +22,7 @@ describe("status-effect", () => {
|
|||
const statusEffect = StatusEffect.NONE;
|
||||
|
||||
it("should return the obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:none.obtain");
|
||||
|
@ -32,7 +32,7 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the source-obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName, sourceText);
|
||||
expect(text).toBe("statusEffect:none.obtainSource");
|
||||
|
@ -42,25 +42,25 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the activation text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectActivationText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:none.activation");
|
||||
});
|
||||
|
||||
it("should return the overlap text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectOverlapText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:none.overlap");
|
||||
});
|
||||
|
||||
it("should return the heal text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectHealText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:none.heal");
|
||||
});
|
||||
|
||||
it("should return the descriptor", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectDescriptor(statusEffect);
|
||||
expect(text).toBe("statusEffect:none.description");
|
||||
});
|
||||
|
@ -70,7 +70,7 @@ describe("status-effect", () => {
|
|||
const statusEffect = StatusEffect.POISON;
|
||||
|
||||
it("should return the obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:poison.obtain");
|
||||
|
@ -80,25 +80,25 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the activation text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectActivationText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:poison.activation");
|
||||
});
|
||||
|
||||
it("should return the descriptor", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectDescriptor(statusEffect);
|
||||
expect(text).toBe("statusEffect:poison.description");
|
||||
});
|
||||
|
||||
it("should return the heal text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectHealText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:poison.heal");
|
||||
});
|
||||
|
||||
it("should return the overlap text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectOverlapText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:poison.overlap");
|
||||
});
|
||||
|
@ -108,7 +108,7 @@ describe("status-effect", () => {
|
|||
const statusEffect = StatusEffect.TOXIC;
|
||||
|
||||
it("should return the obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:toxic.obtain");
|
||||
|
@ -118,25 +118,25 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the activation text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectActivationText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:toxic.activation");
|
||||
});
|
||||
|
||||
it("should return the descriptor", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectDescriptor(statusEffect);
|
||||
expect(text).toBe("statusEffect:toxic.description");
|
||||
});
|
||||
|
||||
it("should return the heal text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectHealText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:toxic.heal");
|
||||
});
|
||||
|
||||
it("should return the overlap text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectOverlapText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:toxic.overlap");
|
||||
});
|
||||
|
@ -146,7 +146,7 @@ describe("status-effect", () => {
|
|||
const statusEffect = StatusEffect.PARALYSIS;
|
||||
|
||||
it("should return the obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:paralysis.obtain");
|
||||
|
@ -156,25 +156,25 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the activation text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectActivationText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:paralysis.activation");
|
||||
});
|
||||
|
||||
it("should return the descriptor", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectDescriptor(statusEffect);
|
||||
expect(text).toBe("statusEffect:paralysis.description");
|
||||
});
|
||||
|
||||
it("should return the heal text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectHealText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:paralysis.heal");
|
||||
});
|
||||
|
||||
it("should return the overlap text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectOverlapText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:paralysis.overlap");
|
||||
});
|
||||
|
@ -184,7 +184,7 @@ describe("status-effect", () => {
|
|||
const statusEffect = StatusEffect.SLEEP;
|
||||
|
||||
it("should return the obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:sleep.obtain");
|
||||
|
@ -194,25 +194,25 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the activation text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectActivationText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:sleep.activation");
|
||||
});
|
||||
|
||||
it("should return the descriptor", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectDescriptor(statusEffect);
|
||||
expect(text).toBe("statusEffect:sleep.description");
|
||||
});
|
||||
|
||||
it("should return the heal text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectHealText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:sleep.heal");
|
||||
});
|
||||
|
||||
it("should return the overlap text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectOverlapText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:sleep.overlap");
|
||||
});
|
||||
|
@ -222,7 +222,7 @@ describe("status-effect", () => {
|
|||
const statusEffect = StatusEffect.FREEZE;
|
||||
|
||||
it("should return the obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:freeze.obtain");
|
||||
|
@ -232,25 +232,25 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the activation text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectActivationText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:freeze.activation");
|
||||
});
|
||||
|
||||
it("should return the descriptor", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectDescriptor(statusEffect);
|
||||
expect(text).toBe("statusEffect:freeze.description");
|
||||
});
|
||||
|
||||
it("should return the heal text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectHealText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:freeze.heal");
|
||||
});
|
||||
|
||||
it("should return the overlap text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectOverlapText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:freeze.overlap");
|
||||
});
|
||||
|
@ -260,7 +260,7 @@ describe("status-effect", () => {
|
|||
const statusEffect = StatusEffect.BURN;
|
||||
|
||||
it("should return the obtain text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
|
||||
const text = getStatusEffectObtainText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:burn.obtain");
|
||||
|
@ -270,25 +270,25 @@ describe("status-effect", () => {
|
|||
});
|
||||
|
||||
it("should return the activation text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectActivationText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:burn.activation");
|
||||
});
|
||||
|
||||
it("should return the descriptor", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectDescriptor(statusEffect);
|
||||
expect(text).toBe("statusEffect:burn.description");
|
||||
});
|
||||
|
||||
it("should return the heal text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectHealText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:burn.heal");
|
||||
});
|
||||
|
||||
it("should return the overlap text", () => {
|
||||
vi.spyOn(i18next, "t").mockImplementation(tMock);
|
||||
mockI18next();
|
||||
const text = getStatusEffectOverlapText(statusEffect, pokemonName);
|
||||
expect(text).toBe("statusEffect:burn.overlap");
|
||||
});
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import Phaser from "phaser";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import * as overrides from "#app/overrides";
|
||||
import { Species } from "#enums/species";
|
||||
import {
|
||||
MoveEffectPhase,
|
||||
} from "#app/phases";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { getMovePosition } from "#app/test/utils/gameManagerUtils";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { NumberHolder } from "#app/utils.js";
|
||||
import Move from "#app/data/move.js";
|
||||
import Pokemon from "#app/field/pokemon.js";
|
||||
import { allMoves, OpponentHighHpPowerAttr } from "#app/data/move.js";
|
||||
|
||||
describe("Moves - Hard Press", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.SNORLAX);
|
||||
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE);
|
||||
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.HARD_PRESS]);
|
||||
});
|
||||
|
||||
it("power varies between 1 and 100, and is greater the more HP the target has", async () => {
|
||||
await game.startBattle([Species.GRAVELER]);
|
||||
const moveToBeUsed = allMoves[Moves.HARD_PRESS];
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, moveToBeUsed));
|
||||
await game.phaseInterceptor.to(MoveEffectPhase);
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon();
|
||||
const movePower = getMockedMovePower(enemy, game.scene.getPlayerPokemon(), moveToBeUsed);
|
||||
const moveMaxBasePower = getMoveMaxBasePower(moveToBeUsed);
|
||||
|
||||
expect(movePower).toBe(moveMaxBasePower * enemy.getHpRatio());
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Calculates the mocked move power based on the attributes of the move and the opponent's high HP.
|
||||
*
|
||||
* @param defender - The defending Pokémon.
|
||||
* @param attacker - The attacking Pokémon.
|
||||
* @param move - The move being used.
|
||||
* @returns The calculated move power.
|
||||
*/
|
||||
const getMockedMovePower = (defender: Pokemon, attacker: Pokemon, move: Move) => {
|
||||
const powerHolder = new NumberHolder(move.power);
|
||||
|
||||
if (move.hasAttr(OpponentHighHpPowerAttr)) {
|
||||
const attr = move.getAttrs(OpponentHighHpPowerAttr);
|
||||
attr[0].apply(attacker, defender, move, [ powerHolder ]);
|
||||
}
|
||||
|
||||
return powerHolder.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the maximum base power of a move based on its attributes.
|
||||
*
|
||||
* @param move - The move which maximum base power is being retrieved.
|
||||
* @returns The maximum base power of the move.
|
||||
*/
|
||||
const getMoveMaxBasePower = (move: Move) => {
|
||||
const attr = move.getAttrs(OpponentHighHpPowerAttr);
|
||||
|
||||
return (attr[0] as OpponentHighHpPowerAttr)["maxBasePower"];
|
||||
};
|
|
@ -0,0 +1,100 @@
|
|||
import { BerryType } from "#app/enums/berry-type";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { Species } from "#app/enums/species";
|
||||
import { Button } from "#app/enums/buttons";
|
||||
import * as overrides from "#app/overrides";
|
||||
import {
|
||||
BattleEndPhase,
|
||||
SelectModifierPhase
|
||||
} from "#app/phases";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||
import PartyUiHandler, { PartyUiMode } from "#app/ui/party-ui-handler";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import Phaser from "phaser";
|
||||
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { getMovePosition } from "../utils/gameManagerUtils";
|
||||
|
||||
|
||||
describe("UI - Transfer Items", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100);
|
||||
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(1);
|
||||
vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([
|
||||
{ name: "BERRY", count: 1, type: BerryType.SITRUS },
|
||||
{ name: "BERRY", count: 2, type: BerryType.APICOT },
|
||||
{ name: "BERRY", count: 2, type: BerryType.LUM },
|
||||
]);
|
||||
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.DRAGON_CLAW]);
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MAGIKARP);
|
||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH]);
|
||||
|
||||
await game.startBattle([Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA]);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.DRAGON_CLAW));
|
||||
|
||||
game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => {
|
||||
expect(game.scene.ui.getHandler()).toBeInstanceOf(ModifierSelectUiHandler);
|
||||
|
||||
const handler = game.scene.ui.getHandler() as ModifierSelectUiHandler;
|
||||
handler.setCursor(1);
|
||||
handler.processInput(Button.ACTION);
|
||||
|
||||
game.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER);
|
||||
});
|
||||
|
||||
await game.phaseInterceptor.to(BattleEndPhase);
|
||||
});
|
||||
|
||||
it("check red tint for held item limit in transfer menu", async () => {
|
||||
game.onNextPrompt("SelectModifierPhase", Mode.PARTY, () => {
|
||||
expect(game.scene.ui.getHandler()).toBeInstanceOf(PartyUiHandler);
|
||||
|
||||
const handler = game.scene.ui.getHandler() as PartyUiHandler;
|
||||
handler.processInput(Button.ACTION);
|
||||
|
||||
expect(handler.optionsContainer.list.some((option) => (option as BBCodeText).text?.includes("Sitrus Berry"))).toBe(true);
|
||||
expect(handler.optionsContainer.list.some((option) => (option as BBCodeText).text?.includes("Apicot Berry (2)"))).toBe(true);
|
||||
expect(handler.optionsContainer.list.some((option) => RegExp(/Lum Berry\[color.*(2)/).exec((option as BBCodeText).text))).toBe(true);
|
||||
|
||||
game.phaseInterceptor.unlock();
|
||||
});
|
||||
|
||||
await game.phaseInterceptor.to(SelectModifierPhase);
|
||||
}, 20000);
|
||||
|
||||
it("check transfer option for pokemon to transfer to", async () => {
|
||||
game.onNextPrompt("SelectModifierPhase", Mode.PARTY, () => {
|
||||
expect(game.scene.ui.getHandler()).toBeInstanceOf(PartyUiHandler);
|
||||
|
||||
const handler = game.scene.ui.getHandler() as PartyUiHandler;
|
||||
handler.processInput(Button.ACTION); // select Pokemon
|
||||
handler.processInput(Button.ACTION); // select held item (Sitrus Berry)
|
||||
|
||||
handler.setCursor(1); // move to other Pokemon
|
||||
handler.processInput(Button.ACTION); // select Pokemon
|
||||
|
||||
expect(handler.optionsContainer.list.some((option) => (option as BBCodeText).text?.includes("Transfer"))).toBe(true);
|
||||
|
||||
game.phaseInterceptor.unlock();
|
||||
});
|
||||
|
||||
await game.phaseInterceptor.to(SelectModifierPhase);
|
||||
}, 20000);
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
import i18next, { type ParseKeys } from "i18next";
|
||||
import { vi } from "vitest";
|
||||
|
||||
/**
|
||||
* Sets up the i18next mock.
|
||||
* Includes a i18next.t mocked implementation only returning the raw key (`(key) => key`)
|
||||
*
|
||||
* @returns A spy/mock of i18next
|
||||
*/
|
||||
export function mockI18next() {
|
||||
return vi.spyOn(i18next, "t").mockImplementation((key: ParseKeys) => key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of range `start - end`
|
||||
*
|
||||
* @param start start number e.g. 1
|
||||
* @param end end number e.g. 10
|
||||
* @returns an array of numbers
|
||||
*/
|
||||
export function arrayOfRange(start: integer, end: integer) {
|
||||
return Array.from({ length: end - start }, (_v, k) => k + start);
|
||||
}
|
|
@ -3,24 +3,16 @@ import {addTextObject, TextStyle} from "./text";
|
|||
import i18next from "i18next";
|
||||
import * as Utils from "#app/utils";
|
||||
|
||||
|
||||
const hiddenX = -150;
|
||||
const shownX = 0;
|
||||
const baseY = 0;
|
||||
|
||||
|
||||
export default class BgmBar extends Phaser.GameObjects.Container {
|
||||
private defaultWidth: number;
|
||||
private defaultHeight: number;
|
||||
|
||||
private bg: Phaser.GameObjects.NineSlice;
|
||||
private musicText: Phaser.GameObjects.Text;
|
||||
private noteText: Phaser.GameObjects.Text;
|
||||
|
||||
private tween: Phaser.Tweens.Tween;
|
||||
private autoHideTimer: NodeJS.Timeout;
|
||||
private queue: (string)[] = [];
|
||||
|
||||
|
||||
public shown: boolean;
|
||||
|
||||
|
@ -29,19 +21,15 @@ export default class BgmBar extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
setup(): void {
|
||||
this.defaultWidth = 200;
|
||||
this.defaultWidth = 230;
|
||||
this.defaultHeight = 100;
|
||||
|
||||
this.bg = this.scene.add.nineslice(-5, -5, "ability_bar_left", null, this.defaultWidth, this.defaultHeight, 0, 0, 10, 10);
|
||||
this.bg = this.scene.add.nineslice(-5, -5, "bgm_bar", null, this.defaultWidth, this.defaultHeight, 0, 0, 10, 10);
|
||||
this.bg.setOrigin(0, 0);
|
||||
|
||||
this.add(this.bg);
|
||||
|
||||
this.noteText = addTextObject(this.scene, 5, 5, "", TextStyle.MESSAGE, {fontSize: "72px"});
|
||||
this.noteText.setOrigin(0, 0);
|
||||
this.add(this.noteText);
|
||||
|
||||
this.musicText = addTextObject(this.scene, 30, 5, "", TextStyle.MESSAGE, {fontSize: "72px"});
|
||||
this.musicText = addTextObject(this.scene, 5, 5, "", TextStyle.BGM_BAR);
|
||||
this.musicText.setOrigin(0, 0);
|
||||
this.musicText.setWordWrapWidth(650, true);
|
||||
|
||||
|
@ -56,16 +44,15 @@ export default class BgmBar extends Phaser.GameObjects.Container {
|
|||
* @param {string} bgmName The name of the BGM to set.
|
||||
*/
|
||||
setBgmToBgmBar(bgmName: string): void {
|
||||
this.noteText.setText(`${i18next.t("bgmName:music")}:`);
|
||||
this.musicText.setText(`${this.getRealBgmName(bgmName)}`);
|
||||
this.musicText.setText(`${i18next.t("bgmName:music")}${this.getRealBgmName(bgmName)}`);
|
||||
if (!(this.scene as BattleScene).showBgmBar) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.musicText.width = this.bg.width - 20;
|
||||
this.musicText.setWordWrapWidth(this.defaultWidth * 4);
|
||||
this.bg.width = Math.min(this.defaultWidth, this.noteText.displayWidth + this.musicText.displayWidth + 30);
|
||||
|
||||
this.bg.width = Math.min(this.defaultWidth, this.musicText.displayWidth + 23);
|
||||
this.bg.height = Math.min(this.defaultHeight, this.musicText.displayHeight + 20);
|
||||
|
||||
(this.scene as BattleScene).fieldUI.bringToTop(this);
|
||||
|
@ -97,5 +84,3 @@ export default class BgmBar extends Phaser.GameObjects.Container {
|
|||
return i18next.t([`bgmName:${bgmName}`, "bgmName:missing_entries"], {name: Utils.formatText(bgmName)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { CommandPhase, SelectModifierPhase } from "../phases";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { PlayerPokemon, PokemonMove } from "../field/pokemon";
|
||||
import { addTextObject, TextStyle } from "./text";
|
||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "./text";
|
||||
import { Command } from "./command-ui-handler";
|
||||
import MessageUiHandler from "./message-ui-handler";
|
||||
import { Mode } from "./ui";
|
||||
import * as Utils from "../utils";
|
||||
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier, SwitchEffectTransferModifier } from "../modifier/modifier";
|
||||
import { PokemonBaseStatModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, SwitchEffectTransferModifier } from "../modifier/modifier";
|
||||
import { allMoves } from "../data/move";
|
||||
import { getGenderColor, getGenderSymbol } from "../data/gender";
|
||||
import { StatusEffect } from "../data/status-effect";
|
||||
|
@ -19,6 +19,7 @@ import {Button} from "#enums/buttons";
|
|||
import { applyChallenges, ChallengeType } from "#app/data/challenge.js";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
import i18next from "i18next";
|
||||
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
||||
import { Moves } from "#enums/moves";
|
||||
|
||||
const defaultMessage = i18next.t("partyUiHandler:choosePokemon");
|
||||
|
@ -85,7 +86,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
private optionsCursor: integer = 0;
|
||||
private optionsScrollCursor: integer = 0;
|
||||
private optionsScrollTotal: integer = 0;
|
||||
private optionsContainer: Phaser.GameObjects.Container;
|
||||
/** This is only public for test/ui/transfer-item.test.ts */
|
||||
public optionsContainer: Phaser.GameObjects.Container;
|
||||
private optionsBg: Phaser.GameObjects.NineSlice;
|
||||
private optionsCursorObj: Phaser.GameObjects.Image;
|
||||
private options: integer[];
|
||||
|
@ -819,7 +821,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
optionEndIndex = this.options.length;
|
||||
|
||||
let widestOptionWidth = 0;
|
||||
const optionTexts: Phaser.GameObjects.Text[] = [];
|
||||
const optionTexts: BBCodeText[] = [];
|
||||
|
||||
for (let o = optionStartIndex; o < optionEndIndex; o++) {
|
||||
const option = this.options[this.options.length - (o + 1)];
|
||||
|
@ -861,27 +863,42 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
const move = learnableLevelMoves[option];
|
||||
optionName = allMoves[move].name;
|
||||
altText = !pokemon.getSpeciesForm().getLevelMoves().find(plm => plm[1] === move);
|
||||
} else {
|
||||
if (option === PartyOption.ALL) {
|
||||
} else if (option === PartyOption.ALL) {
|
||||
optionName = i18next.t("partyUiHandler:ALL");
|
||||
} else {
|
||||
const itemModifier = itemModifiers[option];
|
||||
optionName = itemModifier.type.name;
|
||||
/** For every item that has stack bigger than 1, display the current quantity selection */
|
||||
if (this.transferQuantitiesMax[option] > 1) {
|
||||
optionName += ` (${this.transferQuantities[option]})`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const yCoord = -6 - 16 * o;
|
||||
const optionText = addTextObject(this.scene, 0, yCoord - 16, optionName, TextStyle.WINDOW);
|
||||
const optionText = addBBCodeTextObject(this.scene, 0, yCoord - 16, optionName, TextStyle.WINDOW, { maxLines: 1 });
|
||||
if (altText) {
|
||||
optionText.setColor("#40c8f8");
|
||||
optionText.setShadowColor("#006090");
|
||||
}
|
||||
optionText.setOrigin(0, 0);
|
||||
|
||||
/** For every item that has stack bigger than 1, display the current quantity selection */
|
||||
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER && this.transferQuantitiesMax[option] > 1) {
|
||||
const itemModifier = itemModifiers[option];
|
||||
|
||||
/** Not sure why getMaxHeldItemCount had an error, but it only checks the Pokemon parameter if the modifier is PokemonBaseStatModifier */
|
||||
if (itemModifier === undefined || itemModifier instanceof PokemonBaseStatModifier) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let amountText = ` (${this.transferQuantities[option]})`;
|
||||
|
||||
/** If the amount held is the maximum, display the count in red */
|
||||
if (this.transferQuantitiesMax[option] === itemModifier.getMaxHeldItemCount(undefined)) {
|
||||
amountText = `[color=${getTextColor(TextStyle.SUMMARY_RED)}]${amountText}[/color]`;
|
||||
}
|
||||
|
||||
optionText.setText(optionName + amountText);
|
||||
}
|
||||
|
||||
optionText.setText(`[shadow]${optionText.text}[/shadow]`);
|
||||
|
||||
optionTexts.push(optionText);
|
||||
|
||||
widestOptionWidth = Math.max(optionText.displayWidth, widestOptionWidth);
|
||||
|
|
|
@ -34,7 +34,8 @@ export enum TextStyle {
|
|||
MOVE_PP_HALF_FULL,
|
||||
MOVE_PP_NEAR_EMPTY,
|
||||
MOVE_PP_EMPTY,
|
||||
SMALLER_WINDOW_ALT
|
||||
SMALLER_WINDOW_ALT,
|
||||
BGM_BAR
|
||||
}
|
||||
|
||||
export function addTextObject(scene: Phaser.Scene, x: number, y: number, content: string, style: TextStyle, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle): Phaser.GameObjects.Text {
|
||||
|
@ -146,6 +147,11 @@ export function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraSty
|
|||
shadowXpos = 3;
|
||||
shadowYpos = 3;
|
||||
break;
|
||||
case TextStyle.BGM_BAR:
|
||||
styleOptions.fontSize = defaultFontSize - 24;
|
||||
shadowXpos = 3;
|
||||
shadowYpos = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
const shadowColor = getTextColor(style, true, uiTheme);
|
||||
|
@ -235,6 +241,8 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui
|
|||
return !shadow ? "#f88880" : "#f83018";
|
||||
case TextStyle.SMALLER_WINDOW_ALT:
|
||||
return !shadow ? "#484848" : "#d0d0c8";
|
||||
case TextStyle.BGM_BAR:
|
||||
return !shadow ? "#f8f8f8" : "#6b5a73";
|
||||
}
|
||||
}
|
||||
|
||||
|
|